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.
ArrayAdapter
from an AsyncTask
with OnProgressUpdate
? notifyDatasetChanged()
after each added row? Fragment
/ Loader
approach better? 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
上一篇: android中的BroadcastReceiver中的getApplication
下一篇: 我怎样才能将行添加到列表视图异步?