从后台线程
我的一些用户的更新适配器(也许50)是越来越崩溃,并显示以下错误:从后台线程
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.
如果我理解正确的话,它造成的一个的AsyncTask的doInBackground()
调用adapter.clear();
和adapter.addAll(list);
方法,我需要将它移动到onPostExecute()
。
问题是我不能再现该错误,所以我不能确定它是否修复。 StackOverflow上的一些类似问题似乎表明,仅仅将更新适配器更改为onPostExecute()
方法并不能解决问题。
有谁知道我可以如何使每次在我的设备上发生此错误,以确保修复工作?我不明白它为什么在大多数情况下都能正常工作,但有时只会导致崩溃。
简单的答案:你忘记打电话adapter.notifyDatasetChanged()
。
Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.
获取后台数据和onPostExecute()
更新您的适配器,因为你永远不应该改变从后台线程适配器的内容。在UI线程上执行onPreExecute()
和onPostExecute()
。
我在'onPostExecute()'中调用了该函数,该函数恰好在之后发生。但我更感兴趣的是重现这个错误。出于某种原因,它从来没有发生过我,所以它吱吱作响。 – TimSim 2014-09-30 16:00:05
要重现此问题,请在doInBackground()中更改适配器后尝试休眠。
例如:
@Override
protected Void doInBackground(Void... params) {
adapter.clear();
try
{
Thread.sleep(5000);
}
catch(InterruptedException e){}
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
adapter.notifyDatasetChanged();
}
你不应该调用任何UI事情doInBackground(..)方法。 只是调用它们在onPostExecute(..)以及onPreExecute(..)
例如
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
adapter.clear();
}
按照AsyncTask文档,在 “4个步骤” 的段落。
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
试试这个..
runOnUiThread(new Runnable() {
@Override
public void run() {
adapter.notifyDatasetChanged();
}
});
你在某一个点做在你的列表中的任何插入?如果你是可以模拟的,看看会发生什么 – AndroidEnthusiast 2014-09-30 15:56:52
当'mItemCount'不是零并且'mItemCount!= mAdapter.getCount()':[ListView时,抛出'layoutChildren()'中'ListView'的异常。的java(http://grepcode.com/file_/repo1.maven.org/maven2/org.robolectric/android-all/4.1.2_r1-robolectric-0/android/widget/ListView.java/?v=source) – 2014-09-30 16:01:20
我在'doInBackground()'中用适配器做的唯一事情就是'adapter.clear();'和'adapter.addAll(list)'。到目前为止,我在所有设备上运行了数百次,而不是一次崩溃。 – TimSim 2014-09-30 16:02:31