Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)

like image 361
Jeff Axelrod Avatar asked Aug 16 '12 21:08

Jeff Axelrod


1 Answers

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();
    }
  }
}
like image 70
Jeff Axelrod Avatar answered Sep 25 '22 15:09

Jeff Axelrod