Nav*_*rab 4 android android-listview android-asynctask
我收到此错误:java.lang.IllegalStateException:适配器的内容已更改但ListView未收到通知.确保不从后台线程修改适配器的内容,而只是从UI线程修改.[在ListView(2131034188,类android.widget.ListView)中使用Adapter(类.MainActivity $ ListAdapter)]
这就是我做的,我运行一个AsyncTask并获取json数据,然后,onPostExecute,我调用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();
}});
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我的listView被构建.我已经在几个不同的设备上测试了它,没有它们有任何问题,但有些用户告诉我,我登录并看到这个错误.
我该怎么做才能解决它?怎么了 ?
谢谢
迟来的回复道歉,但在我之前的评论中似乎有疑问:你是contactList
从两个不同的线程修改的.
ListView
缓存元素计数,每当有布局的孩子,它会检查该计数againt在绑定的适配器项目的当前数量.如果计数已更改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() + ")]");
}
Run Code Online (Sandbox Code Playgroud)
来源.
换句话说:这正是你得到的错误.在您的方案中,计数差异是由多个线程修改后备数据集引起的,导致同步问题:后台线程可能会修改数据集,被挂起,然后ui线程可能会在layoutChildren()
没有得到通知的情况下调用关于数据集的变化.
现在,进入解决方案.最简单的方法是确保不ListView
从不同的线程修改绑定到适配器的列表.也就是说,要么制作可以随意修改的副本,要么分配新的列表.
所以,做这样的事情,即在onPreExecute()
方法中AsyncTask
.
新名单:
List<HashMap<String, String>> mNewContactList = new ArrayList<HashMap<String, String>>();
Run Code Online (Sandbox Code Playgroud)
一个(浅)副本:
List<HashMap<String, String>> mNewContactList = new ArrayList<HashMap<String, String>>(contactList);
Run Code Online (Sandbox Code Playgroud)
然后,在doInBackground()
,添加数据mNewContactList
.最后,onPostExecute()
你可以:
mNewContactList
并将其设置为ListView
.mNewContactList
到已经存在contactList
,并呼吁notifyDatasetChanged()
对ListView
. 归档时间: |
|
查看次数: |
12216 次 |
最近记录: |