rellenar la vista de lista desde ListAdapter o SimpleCursorAdapter

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 y 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.

preguntado el 08 de noviembre de 11 a las 10:11

Why not you update your database if data is too old and new data available on web and then use it with cursor? -

I want to display the data directly from the web and then update the database in the background. -

Instead of display data directly from the web I recommended you to first update the database and then just display that data with cursor, So you can avoid use of arraylist and also reparsing data for display and to store in database. -

Given the tests I've done so far with SQLite, I'm pretty sure that would significantly decrease the response time, so it's not an option at this point. -

2 Respuestas

Of course you can use a SimpleCursorAdapter y un AsyncTask. Pero con el Paquete de compatibilidad con Android you can start using the CursorLoader API with Android 1.6. The Loader API makes it easier to manage the lifecycle of the Cursors.

Sugeriría usar el CursorLoader API to retrieve a Cursor a partir de una 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 (o 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 al 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);

respondido 08 nov., 11:15

Thank you for this answer; it's probably the best long term solution, but for deadline purposes, I'm implementing something like the other answer for now. - Conejo Trueno

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 
} 

respondido 08 nov., 11:14

I'm enjoying your idea, but a bit worried about my ability to extend BaseAdapter in a way that includes the functionality of both DBCursor and ArrayAdapter .... - Conejo Trueno

I am assuming data coming from DB and Web can be wrapped in "DataEntry" object. After that, you use only your adapter to display the data. - hovanessyan

okay I'm going to look for some tutorials on extending BaseAdapter, and select your answer if I can get it to work... thanks for your answer! - Conejo Trueno

You're welcome, this is the application I used some time ago, to get started: code.google.com/p/myandroidwidgets/source/browse/trunk/… - hovanessyan

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.