Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to populate a listview asynchronously?

I am wondering how I should implement a ListAdapter that loads its views asynchronously into a ListView? I want to do this because I am populating the list with information from my database, which is making my activity a bit slow to load at times.

like image 469
Emil Sjölander Avatar asked May 11 '11 17:05

Emil Sjölander


4 Answers

You can use an AsyncTask and use the onPostExecute methods to publish the newly loaded results:

private ArrayAdapter adapter = new YourArrayAdapter();

private class YourAsyncTask extends AsyncTask<Void, Void, List<YourItem>> {

    @Override
    protected void onPreExecute() {
        // start loading animation maybe?
        adapter.clear(); // clear "old" entries (optional)
    }

    @Override
    protected List<YourItem> doInBackground(Void... params) {
        // everything in here gets executed in a separate thread
        return DataBase.getItems();
    }

    @Override
    protected void onPostExecute(List<YourItem> items) {
        // stop the loading animation or something
        adapter.addAll(items);
    }
}
like image 68
whlk Avatar answered Oct 19 '22 15:10

whlk


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

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 24
Jeff Axelrod Avatar answered Oct 19 '22 14:10

Jeff Axelrod


The easiest thing is to use an AsyncTask to do the loading and call publishProgress as each item is loaded (or, if you want to load all items and have them appear all at once, update the UI in onPostExecute

like image 44
Ted Hopp Avatar answered Oct 19 '22 15:10

Ted Hopp


Is .notifyDataSetChanged() possibly what you're after? Each time you add a new item to the list that backs the ArrayAdapter, you can call .notifyDataSetChanged() on that adapter instance to tell it to refresh. This way your ListView can gradually build up and display each item as they're added to the list.

like image 1
Trevor Avatar answered Oct 19 '22 13:10

Trevor