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.
Related
So, I am running up against a limitation of the Parse SDK here, and I don't know how to proceed.
I have a ListView that I am setting the adapter to from a subclass of the ParseQueryAdapter, which itself extends the BaseAdapter class.
Normally with an adapter, I pass the list along to the Adapter constructor in order to get access to the list I am dealing with, so that I can call getCount, getItem, etc. by accessing the size/index of that ArrayList.
I can't do that with the ParseQueryAdapter because it takes a ParseQueryFactory as part of the constructor, and it doesn't resolve it's items until they are fetched from the Parse app online...
Now the ParseQueryAdapter does have a List of Objects, which is exactly what I need, expect that it is Private... so even though the getItem() and getCount() methods exist, there is no way - AFAIK - to use them, as I have no access to the dataset that is fuelling my adapter...
Further to this, I would normally use getView(), which returns a position alongside my View, and everything would be snappy. Except Parse overrides that and provides a getItemView() method which resolves the Parse Object that is fetched from the cloud and passes it instead of the integer for position...
So, two questions here:
1) Is there another way in which I can access the list that is feeding an adapter ? I can hack a way to pass the resolved query into a list and pass that into the adapter later, by listening to addOnQueryLoadListener(), but that seems bad design and might take a while, handcuffing my UI.
2) Am I being naive in my understanding of how to use get getItem() and getCount() methods ?
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.
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
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.
I'm using an AutoCompleteTextView with an ArrayAdapter which works like supposed.
The problem is, that I have to change the Array with the Autocomplete-Values. Calling notifyDataSetChanged() doesn't help. No changes are shown.
Do you know something to get around this problem?
Do not modify the ArrayList and call notifyDataSetChanged() as it will have no effect on ArrayAdapters (implementation seems broken).
Use clear(), add(), insert(), and remove() directly on your ArrayAdapter instead of those methods on your ArrayList.
You need to add more details to the question but based on a guesstimate of you problem, I would say that there is some problem in the implementation.
notifyDataSetChanged() informs the view to reload the data. If the data set up methods in the ArrayAdapter reference an unchanged data entity, notifyDataSetChanged() will have not effect.
A custom adapter implementation that extends ArrayAdapter will generally have an internal data structure that is the source of data for the adapter and which will contain the AutoComplete values you require.