我得到这个错误: java.lang.IllegalStateException: 适配器的内容已更改但 ListView 未收到通知。确保你的适配器的内容不是从后台线程修改的,而只是从 UI 线程修改的。 [在 ListView(2131034188, class android.widget.ListView) with Adapter(class .MainActivity$ListAdapter)]
这就是我所做的,我运行一个 AsyncTask 并获取 json 数据,然后,在 PostExecute 上,我调用 ListAdapter 将数据生成到 ListView 。
@Override
protected Void doInBackground(Void... arg0) {
Spots_tab1_json sh = new Spots_tab1_json();
String jsonStr = sh.makeServiceCall(url + page, Spots_tab1_json.GET);
if (jsonStr != null) {
JSONObject jsonObj = new JSONObject(jsonStr);
contacts = jsonObj.getJSONArray(TAG_CONTACTS);
for (int i = 0; i < contacts.length(); i++) {
JSONObject c = contacts.getJSONObject(i);
String onvan = new String(c.getString("onvan").getBytes("ISO-8859-1"), "UTF-8");
String id = new String(c.getString("id").getBytes("ISO-8859-1"), "UTF-8");
String dates = new String(c.getString("dates").getBytes("ISO-8859-1"), "UTF-8");
String price = new String(c.getString("gheymat").getBytes("ISO-8859-1"), "UTF-8");
HashMap<String, String> contact = new HashMap<String, String>();
contact.put("onvan", onvan);
contact.put("img", new String(c.getString("img").getBytes("ISO-8859-1"), "UTF-8"));
contactList.add(contact);
}
}
}
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (!isCancelled() && goterr == false) {
final ListAdapter ladap=new ListAdapter(MainActivity.this, contactList);
lv.setAdapter(ladap);
runOnUiThread(new Runnable() {
public void run() {
ladap.notifyDataSetChanged();
}});
}
}
然后,我的 listView 就构建好了。我在几个不同的设备上测试过它,没有一个有任何问题,但一些用户告诉我,我登录并看到这个错误。
我应该怎么做才能解决?怎么了 ?
谢谢你
最佳答案
对于迟来的回复深表歉意,但它在我之前的评论中似乎是可疑的:您正在从两个不同的线程修改 contactList
。
ListView
缓存元素计数,每当它必须对其子项进行布局时,它会再次检查此计数与绑定(bind)适配器中的当前项目数。如果计数已更改并且未通知 ListView
,则会抛出错误:
else if (mItemCount != mAdapter.getCount()) {
throw new 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(" + getId() + ", " + getClass()
+ ") with Adapter(" + mAdapter.getClass() + ")]");
}
Source .
换句话说:这正是您遇到的错误。在您的场景中,计数差异是由多个线程修改支持数据集引起的,从而导致同步问题:后台线程可能会修改数据集,被挂起,然后 ui 线程可能会调用 layoutChildren ()
而未收到有关数据集更改的通知。
现在,进入解决方案。最简单的方法是确保您没有修改绑定(bind)到来自不同线程的 ListView
适配器的列表。也就是说,要么制作一份您可以自由修改的副本,要么分配一个新列表。
所以,做这样的事情,即在 AsyncTask
的 onPreExecute()
方法中。
新列表:
List<HashMap<String, String>> mNewContactList = new ArrayList<HashMap<String, String>>();
(浅)副本:
List<HashMap<String, String>> mNewContactList = new ArrayList<HashMap<String, String>>(contactList);
然后,在doInBackground()
中,将数据添加到mNewContactList
。最后,在 onPostExecute()
中,您可以:
- 使用
mNewContactList
创建一个新适配器并将其设置到ListView
。 - 或者(如果您没有复制原始列表)将
mNewContactList
的内容添加到已经存在的contactList
并调用notifyDatasetChanged()
在ListView
上。
关于android - 适配器的内容已经改变但是ListView没有收到通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26521683/