如何从网络加载数据时快速更新android listview

时间:2014-05-05 02:41:34

标签: java android listview android-listview

我有一个普通的listview / listadapter,我正在使用AsyncTask从网络加载大量数据。完全下载并解析所有数据大约需要5秒钟。

我在处理数据时没有将listview清空5秒,而是希望在处理数据时对其进行更新,以便用户在准备好时可以查看并滚动列表项。处理每件物品需要大约20-50毫秒,并准备好展示。

有人可以帮我解决一下如何实现这一目标。

我试过这段代码只刷新每500毫秒。当新项目处理完毕后,我每隔20到50ms从AsyncTask调用onNewItemReady():

public void onNewItemReady(Object item) {
    mData.add(item);

    long diff = SystemClock.elapsedRealtime()-mLastRefresh;
    if (diff > 500) {
        mAdapter.setData(mData);
        mAdapter.notifyDataSetChanged();
        mLastRefresh = SystemClock.elapsedRealtime();
    }
}

但如果我在加载所有数据之前滚动列表视图,则会收到以下错误:

> 05-04 19:22:59.638: E/AndroidRuntime(24349):
> java.lang.IllegalStateException: The content of the adapter has
> changed but ListView did not receive a notification. Make sure the
> content of your adapter is not modified from a background thread, but
> only from the UI thread. Make sure your adapter calls
> notifyDataSetChanged() when its content changes. [in
> ListView(16908298, class android.widget.ListView) with Adapter(class
> MyAdapter)]

谢谢!

编辑:我没有从后台线程刷新适配器。正在从AsyncTask的onProgressPublished中调用onNewItemReady()。

2 个答案:

答案 0 :(得分:0)

正如logcat消息所示,您正在尝试从后台线程(可能是AsyncTask)刷新listview(在UI线程上),所以您需要做的就是在完成doInbackground()的执行后AsyncTask,您应该刷新asynctask的onPostExecute()中的列表视图。

为了避免用户在下载过程中进行互动,您应该在onPreexcecute()中显示进度对话框。

所以你的Asynctask应该是这样的:

class YourAsyncTask extends AsyncTask{
ProgressDialog pd;
onPreExecute(){
 // show progress dialog here..
}

doInBackground(){
// perform network operation here and collect collect data
}

onPostExecute(){
// dismiss dialog box.
// refresh listview
}

}

请注意,这只是代码的蓝图,正确的语法请参考this

<强>替代 另外,正如您所说的那样,您正在加载大量数据并且需要大约5秒钟(这是很多时间),建议使用Pull-to-refresh,因为它将load data on demand。你可以google它,那里有很多东西。

答案 1 :(得分:0)

我正在使用&#34;无尽的适配器&#34;并显示添加的#34; loading&#34;当用户滚动到底部时,在我的列表视图底部查看。我从Google i / o 2013应用程序中获取了我使用的代码。显然这段代码导致了这个问题。我已经删除它并用更简单的footerview替换它,问题已经消失。

这是我在适配器中使用的代码:

@Override
public int getCount() {
    if (mData != null) {
         return mData.size() + (
              ((mDataTask.isLoading())        // we are already loading
             || mDataTask.hasMoreResults()    // or there are more results
             || mDataTask.isErrored())     // or there's an error
           ? 1 : 0);
        }
   return 0;
}

而不是这段代码,我只是在开始加载时添加一个footerview,并在onPostExecute完成时将其删除。