How can I add rows to a listview asynchronously?

I need to populate a long ListView with data from the network, say 2-3 seconds for the entire data collection. I don't want the user to see a loading Dialog and wait for the entire list download. Instead I want to update the ListView as each item becomes available.

  • How can I do this?
  • I presume by adding to the ArrayAdapter from an AsyncTask with OnProgressUpdate ?
  • Do I have to issue a notifyDatasetChanged() after each added row?
  • Is the Fragment / Loader approach better?
  • Is there a tutorial or API demo reference implementation for a case like this?
  • It's not important that the data be fetched entirely before the Activity dies (ie Service is unnecessary)


    The best approach I've seen so far is from CommonsWare. It was found in this related answer.

    Apparently there is nothing wrong with calling add without notifyDatasetChanged() .

    public class AsyncDemo extends ListActivity {
      private static final String[] items={"lorem", "ipsum", "dolor",
                                          "sit", "amet", "consectetuer",
                                          "adipiscing", "elit", "morbi",
                                          "vel", "ligula", "vitae",
                                          "arcu", "aliquet", "mollis",
                                          "etiam", "vel", "erat",
                                          "placerat", "ante",
                                          "porttitor", "sodales",
                                          "pellentesque", "augue",
                                          "purus"};
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        setListAdapter(new ArrayAdapter<String>(this,
                            android.R.layout.simple_list_item_1,
                            new ArrayList<String>()));
    
        new AddStringTask().execute();
      }
    
      class AddStringTask extends AsyncTask<Void, String, Void> {
        @Override
        protected Void doInBackground(Void... unused) {
          for (String item : items) {
            publishProgress(item);
            SystemClock.sleep(200);
          }
    
          return(null);
        }
    
        @Override
        protected void onProgressUpdate(String... item) {
          ((ArrayAdapter<String>)getListAdapter()).add(item[0]);
        }
    
        @Override
        protected void onPostExecute(Void unused) {
          Toast
            .makeText(AsyncDemo.this, "Done!", Toast.LENGTH_SHORT)
            .show();
        }
      }
    }
    

    Just to make sure, ListView 's adapter nor its underlying data can't be updated from thread other than the UI thread. Updates must be executed on the main application thread. Non-UI threads can use post() or runOnUiThread() , etc. to invoke an update.

    Calling notifyDatasetChanged() just like that is rather not good practice, it should be called by the Adapter itself or the object changing the data.

    As network operation is slow, consider if it woudn't be desirable to store downloaded data in database . Than you end with implementing some sort of CursorAdapter , best with the use of Loader , so that when you update database in your working thread, ListView will be notified automatically about the changes.


    I think you can start here: http://www.vogella.com/articles/AndroidPerformance/article.html

    So, You need to make an asynchronous call to a server for data. Or you could run a background task for that.

    You can Google for AsyncTask or search here on stackoverflow that. Here is example: AsyncTask Android example

    链接地址: http://www.djcxy.com/p/11086.html

    上一篇: android中的BroadcastReceiver中的getApplication

    下一篇: 我怎样才能将行添加到列表视图异步?