I am working on android app in which I am using adapters to populate the data in a listview. I am confused where we should use BaseAdapter. I read many questions where it is written that we should use ArrayAdapter for arrays and arraylist that is ok and CursorAdapter in case of cursor.
I know BaseAdapter is the super class of ArrayAdapter and CursorAdapter. I have checked already this question What is the difference between ArrayAdapter , BaseAdapter and ListAdapter but it don't explain when we should use BaseAdapter.
When should I use BaseAdapter ?
You should use it:
if your model data is not already in a data structure for which there is a concrete ListAdapter class, and
if you determine that creating a custom adapter will be better for the user, or perhaps less development work for you, than would be reorganizing your data structure
For example, suppose that you use JSONArray to parse a snippet of JSON. JSONArray does not implement the List interface, and therefore you cannot use it with ArrayAdapter. None of the other adapters match. Yet, you want to show this JSONArray in an AdapterView. In that case, your choices are:
roll through the data and convert it into an ArrayList, so you can use ArrayAdapter, or
create a custom subclass of BaseAdapter that can adapt a JSONArray (a JSONArrayAdapter)
stop using JSONArray and instead use something else for parsing your JSON, like Gson, which can populate a List directly, allowing you to use ArrayAdapter
If your data is available in a Collection you can go with an ArrayAdapter. (use the addAll method to put your data in the adapter)
If your data is not in a Collection: then you can't and you must find another adapter that suits your needs. (typically: use a CursorAdapter when data comes from a database)
If you can't find any existing adapter working fine with your data structure/data source : you can write a subclass of BaseAdapter to support your own data structure.
If you plan to display your data in a ListView (this is a common use-case): then you must ensure that your adpter also implements ListAdapter (because the ListView needs a ListAdapter).
Note that ArrayAdapter and CursorAdapter implements ListAdapter.
Related
I have a CustomListView in my android app. Each item consists of two pieces of text which are to be retrieved from an online SQL database. I'm using a Model class called ListModel and a custom adapter called CustomAdapter. I'm using an Asynctask to download the model data from the internet. But the problem is that, adding of a ListModel object to my ArrayList is not working when I do it in the onPostExecute method of my Asynctask. So, the listview is not getting updated. How do I display the Model items on my Custom List as soon as they get downloaded? Is there any way to do that?
This type of problems occures when adapter not properly notify after data downloaded. Notify your adapter in postExecute by notifyDataSetChanged () method
Generally this is because notifyDataSetChanged() isn't called on the arrayadapter. (but stacktraces/your code would be helpful)
In addition, this is a prime use of an in-memory SQLite database (if you plan on doing any custom queries)
Or a full on-disk SQLite DB if you want to cache data.
(Adding a content provider(by just surrounding the SqliteDB) would also be nice if you want to abstract away some more and provide observers, etc. )
I want to create a custom list in which items are added or removed dynamically (say when a button is tapped). The problem is I have very little knowledge of lists in android. I have gone through various tutorials on creating a custom list in android but none of them shows how to dynamically add contents to it
What I know so far:
1) I have to create a model class to store data.
2) I have to create an adapter class.
3) Pass the objects of the model class as an arraylist to the adapter.
3) Bind listview to the adapter
What's confusing me:
1) I know I have to create an apapter class, but what's really confusing me is what kind of adapter ? i.e. ArrayAdapter, BaseAdapter ??
2) What and How will I feed adapter? I will be fetching data from the Sql lite database and I want the results to be displayed in my custom made list.
3) How will I update my list when a new record is added to the database ? I know how to populate listview from a static array but its of no use in my project.
I need little guidance where should I start from ?
1) You can use ArrayAdapter.
2) After you create your own arraylist, you can pass it for first time, listview.setAdapter(...
3) After you refresh your data you can call this method, ((ArrayAdapter)listView.getAdapter).notifyDataSetChanged(). This will ensure your listview refresh.
The below link is a good example:
https://github.com/thecodepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView
I have a seperate DatabaseHandler("db") Class which extends SQLiteOpenHelper BUT NOT ACTIVITY which means this is a seperate class file which is not related to any activity. If you ask why i have such a class not in activity because i like keeping my files organized.
So i have listview in a fragment and i have a "DatabaseHandler.getAllRows()" function in that class which returns a "List" Object. Then i want to use this list to populate my listview.
So when this class is a seperate class which is not related to any activity, i can't use simplecursorAdapter since it wants a context in paramteres part when creating with new(i tried to send parameter as context but didnt work) so i need to use something else....
I can change return type, i can use another thing instead of listview.. just give me a good advice for how to populate listview or show table rows NICELY.
If you want a real simple solution, you can store your rows as an array, and use ArrayAdapter to display them. You can override the getView to display the results in your preferred way.
If this solution is not good enough, I think you will have to implement your own Adapter, which might be a good idea anyway.
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
I'm making a new Android app that essentially mirrors data available on our website. The GUI will show either a ListView with images and text in each item, or a RelativeLayout that will display details of a single item.
In order to increase responsiveness in this app, I'd like to read data from the internal DB if the data is recent enough, and read data from the server's API (JSON over http) if the internal data is too old (and then populate the internal DB with the new data).
From the basic tutorials, it seems that one should use the DB and SimpleCursorAdapter (*) when reading from the internal DB. But when reading from the web, I guess I'd be using an ArrayList and ArrayAdapter.
Is there some type of Adapter that can handle both situations?
(*) I know the latest thing is to use LoaderManager with a CursorLoader, but I'm trying to support Android 2.1. I figure I can put the SimpleCursorAdapter into an AsyncTask and avoid ANR.
Of course you can use a SimpleCursorAdapter and an AsyncTask. But with the Android Compatibility Package you can start using the CursorLoader API with Android 1.6. The Loader API makes it easier to manage the lifecycle of the Cursors.
I would suggest using the CursorLoader API to retrieve a Cursor from a ContentProvider or a database. And use an AsyncTask (or a custom implementation of AsyncLoader) to fetch the Data from the server and update ContentProvider.
If you use two different AsyncTasks (or Loaders) for each task (loading cursor and updating data) you can make your ListView update itself automatically if the data in the db has changed.
To do so set a notification Uri on the Cursor that you retrieved from the db:
cursor.setNotificationUri(getContentResplver(), Uri.parseString("mydata://someuri"));
And if you have updated the data, send a notification for that Uri:
getContentResolver().notifyChange(Uri.parseString("mydata://someuri"), null);
I think you can write a custom Adapter, extending BaseAdapter class and use it for both cases.
In your class, that extends BaseAdapter, you will have a List<DataEntry>, where DataEntry is Java POJO class, representing the data coming from web or db (assuming it has the same properties). Assuming you have populated the List<DataEntry> with DataEntry objects, already containing data you can do as follows:
1) In the getView() method of the class that extends BaseAdapter, in the inflate, you will use an xml layout, that's basically represents 1 data row. Assuming you will display data via TextView, the 1 data row layout will have as many TextView elemnts, as the number of data-fields of your DataEntry object. After the inflate, you put values in the TextViews like:
TextView someTextViewToDisplayField = (TextView) convertView.findViewById(R.id.yourID);
someTextViewToDisplayField.setText(String.valueOf(dataEntry.getWhateverProperty()));
2) in the process where you update the UI in your layout you should have a ListView like:
<ListView android:id="#+id/YourListViewID" android:layout_width="fill_parent"
android:layout_height="wrap_content"></ListView>
and after that you initialize your class that extends BaseAdapter
ListView listView = (ListView) findViewById(R.id.YourListViewID);
YourClassExtendingBaseAdapter adapter =
new YourClassExtendingBaseAdapter(this, listOfEntryDataObjects);
listView.setAdapter(adapter);
the listOfEntryDataObjects is List<DataEntry> already populated with data. The 'this' in the constructor is the context associated with the current Activity, you make the call from.
Structure of class that extends BaseAdapter:
public class YourClassExtendingBaseAdapter extends BaseAdapter {
private Context context;
private List<DataEntry> entries;
public YourClassExtendingBaseAdapter(Context context,
List<DataEntry> entries) {
this.context = context;
this.entries = entries;
}
// Overwriting necessary methods
}