AdapterView<?> parent versus adapter - android

I have a ListView. Naturally I pass an adapter to it, say mDogAdapter. My ListView also implements setOnItemClickListener.
So here is my question: in the context of getting an item from the adapter, what is the difference between these two?
Dog dog =(Dog) parent.getItemAtPosition(position);
Dog dog = mDogAdapter.getItem(position);

There's no difference.
The AdapterView's getItemAtPosition() method will call getItem() on the adapter in its implementation.
It's up to you to decide which makes more sense. If it's possible that you may use a different adapter at some point, you should consider using the AdapterView's getItemAtPosition() method -- let the AdapterView deal with getting the correct data from its Adapter.

Related

What is dataset of BaseAdapter

When we use ArrayAdapter we pass something like a list to the super class. But base adapter constructor doesn't have any parameters. How does this class find the data set? I have seen in some examples they just define an array and override the functions without specifying the list as the Dataset. So how does the class understand this is the dataset? What if we define more than one list in the derived class?
Edit:
I think I should clarify my question. When we use ArrayAdapter the dataset is specified and the program knows what to iterate and calls getView for each of them. But in BaseAdapter we only define a list and override 4 functions and it works! My question is why does it work?! we didn't specify the dataset we just specify the getView body and it returns a view. I don't understand how the program finds the dataset.
As the documentation explains it well :
Common base class of common implementation for an Adapter
Means you have to do the implementation.
http://developer.android.com/reference/android/widget/BaseAdapter.html
How does this class find the data set?
It doesn't. Your subclass of BaseAdapter manages the data set.
What if we define more than one list in the derived class?
So long as you implement the abstract Adapter methods properly (getCount(), getView(), getItem(), getItemId(), ...), how you manage your own data is up to you.
Well after more considerations on the codes I think this is how base adapter works:
It loops the getView() function with 'position' parameter to be from 0 to what is returned by getCount().
we must override getCount() and send the correct index of the last item of dataSet. Each time getView() is called we can work with the views and any list we want according to the current position.
And I think the main difference between ArrayAdapter and BaseAdapter is that ArrayAdapter finds the last index of the list when we pass it to the super class but in base Adapter we should define the last index. Implementation of getView() is the same and we can use any list we want in getView. The trick was only about position parameter.

StableArrayAdapter vs ArrayAdapter

I am looking at this ListView Tutorial:
ListView Tutorial
and I was wondering how much better is to create my own ArrayAdapter, rather than just using and ArrayAdapter.
In the Tutorial it defines a "StableArrayAdapter", what exactly does this means? If I use a regular ArrayAdapter, could it be dangerous for some reason?
The two previous answers are absolutely right, but just to address more directly your question and in case someone else has the same doubt than you; a regular ArrayAdapter is not dangerous at all, the only "problem" is that it might not fulfill your needs, in which case you will have to create your own adapter, as the author of the tutorial did by creating what he called StableArrayAdapter in the end of the ListViewExampleActivity class.
Don't get lost by the name, which I guess comes from the fact that the overwritten method "hasStableIds" always returns true, it doesn't mean that the regular ArrayAdapter creates problems.
ArrayAdapter: It is merely a way to provide data to a ListView. It is also a BaseAdapter that is backed by an array of objects.
CustomAdapter: If if your ListView is a normal and simple ListView (wherein you are having one TextView per item in the list), then the use of ArrayAdapter would be apt.
But it is recommended you to create your own CustomAdapter which extends an ArrayAdapter that you can use for providing data to your ListView. This way you can easily extend your ListView to include more that one TextView or even ImageView (to show images).
CursorAdapter: Cursor Adapter is used when you have Data in a Cursor (typically when you are retrieving data from a database. The Cursor must include a column named "_id" or this class will not work.
If you are using a simple ListView, like merely a TextView per item, then just use the standard ArrayAdapter, on the other hand, if you want a custom item in the list, as in a combinations of views within each item in the ListView, then extend the ArrayAdapter and implement it to your needs.
StableArrayAdapter is merely an extended version of ArrayAdapter, but in StableArrayAdapter they have overridden the method hasStableIds() of BaseAdapter to return true.
You can check this in the following links:
StableArrayAdapter -
Override hasStableIds to return true
ArrayAdapter -
Has not Override hasStableIds but extended BaseAdapter
BaseAdapter -
Has hasStableIds but returning false
Now Question is What is the use of StableIds
This Indicates whether the item ids are stable across changes to the underlying data. If True then same id always refers to the same object. for more info

How to use ArrayLists in ListAdapter (ListView)?

)
I found a tutorial about using the ListView in android. But I have a question about it. Here the tutorial:
http://www.vogella.com/articles/AndroidListView/article.html#listadvanced_interactive
You have to scroll to section 13.2.
The idea of the tutorial is on one hand you have a ListView (with checkboxes in each item), on the other hand you have an ArrayList (the items of the ArrayList are objects, which contain the information which are displayed in the items of the ListView, e.g. CheckBox checked or not, text etc.). The adapter schould keep both things equal. If you change the ArrayList, the ListView will be changed, too.
But now my question. If the user touch on one item of the List, the adapter will call the method "onCheckedChanged". But what happen there? An object will create there and get a tag from the the CheckBox. Ok. Now the method is done. The garbage collector will destroy the object or doesn't? What is when I need this infomation from there in my Activity. Imagine I have a button "Delete" under my list. So I have to transfer these information from the listener of the adapter to my Activity. How I can ensure that I use the same ArrayList with the right information in every class?
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) viewHolder.checkbox
.getTag();
element.setSelected(buttonView.isChecked());
}
I hope you know what I mean. Can you explain it to me please?
Sorry for the language, but english isn't my mother tongue.
Bye
If I understand your question, the response is in the Chapter 14.1 of the tutorial you gaved...
If you want to do some treatment when delete is checked you add a listener in the ListView.
These functions normally have the position clicked and you can do whatever you want knowing the position clicked. For exemple:
list.setOnItemLongClickListener(new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(MyList.this,
"Item in position " + position + " clicked",
Toast.LENGTH_LONG).show();
// Return true to consume the click event. In this case the
// onListItemClick listener is not called anymore.
return true;
}
});
I'm not totally sure I understand you're question. There's a lot to unpack in there but I will give it a shot. To understand what's going on you need to understand the relationship between the ListView and the data that backs it which is contained in the ListAdapter.
The ListView displays the data contained in the ListAdapter. The ListAdapter gets its data from some other source, in this case its the ArrayList that you're referring to. Why use an ArrayList? In the tutorial its not entirely clear because the example uses a fixed set of data (e.g. a list of operating systems) that are written out as strings. In practice, however, often times you are using a dynamic list, like a list of users, places, whatever.
The ArrayList holds the objects that will eventually be displayed. This is the "models" class in the tutorial. The same applies for any other class of data, like a list of places. If you imagine a place as a class, that class would contain fields that describe the place (e.g. address, a description, some other unique features). As data is downloaded from some location, a new instance of place would be created for each location. Those objects would be collected in an ArrayList. When the downaloding process was finished, you would then begin the process of passing the contents of that ArrayList to the ListAdapter so that the ListView could eventually be updated.
How do you know you will always use the right ArrayList? Because your ArrayList is linked to you ListAdapter. The data the the ListAdapter processes, whether a list of models or users, is supplied by the ArrayList. You cannot use the wrong one. The same goes for the ListAdapter. Because you must set the adapter that the ListView is linked it it will always pull from the correct source. You cannot use the wrong data.
What's happening with the onCheckChanged listener, if you pay close attention, is that the user is really just updating a field contained in the model class. Each modle has an isChecked field. When the check box is clicked, that value for the object is updated. This is how you know what is checked and what is not.
Response to: "Nobody told the adapter "Hey it belongs to the list, which is your source"
Look at the documentation for ArrayAdapter
and for ListView
The constructors for the ArrayAdapter all take some list of object as an argument. This list would be the list of object that will be displayed within the ListView.
Additionally the ListView requires that you call setAdapter which takes some ListAdapter as its argument. This is what actually tells the ListView the source of the data it is going to display.
In that sense, the List, ListAdapter, and ListView are all linked together.

Is the textViewResourceId argument always necessary?

While writing my own adapter that extends the ArrayAdapter class, I came across the different constructors available and I noticed they all require a textViewResourceId parameter. So initially, I decided that I would feed my custom adapter class android.R.id.text1:
MyAdapter adapter = new MyAdapter(this, R.layout.myRow, android.R.id.text1);
However, later on during my development, I decided to override getView method where I would
TextView label = (TextView) myRow.findViewById(android.R.id.text1);
label.setText("Position #" + position);
Which worked fine. But then this question came to mind: if I'm doing the logic for how to display the row, is it really necessary to provide a textViewResourceId to the constructor when I initiate my custom adapter? Or is it the case that when you override getView, that parameter is no longer necessary? If my thinking is correct, what is the common practice for instantiating the adapter knowing that you will be overriding the display behavior anyways?
If you are overriding getView you do NOT need to specify a proper textViewResourceId.. You can pass in 0. The only time the ArrayAdapter tries to access that ID is within getView.. Since you are overriding getView and providing your own view textViewResourceId is never accessed..
Since the super class expects a view ID.. you still need to pass in a view ID into the super call.. however, it can just be 0 since it will never be used
ArrayAdapter Source confirming all of this
If you do not specify a proper textViewResourceId and do not override getView.. getView in the ArrayAdapter assumes your entire view is a TextView.. If your view is not a TextView.. you will end up with crashes from a ClassCastException..
you don't need to use any kind of build in adapter.
you can extend the BaseAdapter and make your own rules of what to show , what type of data to hold etc...
in fact , i almost never used the built in adapters that android has out of the box , because using the baseAdapter is very easy as it is.

Android Bind Spinner to Class

I'm having some trouble with the Spinner widget. Given the following code:
ArrayList<Person> people= new ArrayList<Person>();
Person = null;
for(int i = 0; i!= 10; i++) {
p = new Person();
s.setID(i);
s.setName("Name " + i);
people.add(s);
}
I'm using the following code to bind it to a Spinner:
Spinner spinner1 = (Spinner) findViewById (R.id.spinner);
ArrayAdapter<Person> adapter = new ArrayAdapter<Person>(this, android.R.layout.simple_spinner_item, people);
spinner1.setAdapter(adapter);
What I would like is for the value (id) to be hidden but passed when selected, and the name to appear. Any help is appreciated.
Thanks.
If I understand your question correctly you would like the name to appear in the spinner dropdown view. When an item is selected you would like to return the id.
There are 2 ways you can approach this.
The simplest way is to implement a toString() that returns the name in your Person object. The ArrayAdapter will return this value when binding the text values of your object to the dropdown view.
Then in your activity you can set the onItemClickListener for the Spinner and call on the adapter.getItemAtPosition(position) to retrieve the Person object. From that person object you can get your id.
The second approach is to extend the ArrayAdapter and implement the getView and getDropDownView and getItem methods. The getView is responsible for creating the rows you see when you click the spinner. The getDropDownView is responsible for creating the view you see in the spinner. And the getItem method will return the object or in your case the id at that specified position. You should bind the name of the Person element to a textview in your getView and getDropDownView methods. After you've created your custom ArrayAdapter you should set the onItemClicKListener for the Spinner and handle it just as I have mentioned above.
The first approach is simple but the second approach is far superior and will yield much greater control over your adapter, especially when you begin to develop something much more complex.
Hope that helps.
very old post -- just came across looking for something else -- noiced a mistake (probably just oversight)
jagsund is mostly right, accept, he got the definion of getView and GetDropDownView wrong - its actually the opposite of what he said : getView shows the content inside the spinner control, getDropDownView creates the view rows that you see when you click on the spinner.
So, unless you click on the spinner, getDropDownView will not even get called - you'll see this if you override ArrayAdapter

Categories

Resources