java.lang.IllegalStateException: The content of the adapter has changed but

  • Post author:
  • Post category:java




使用listview 的时候出现如下错误:


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.


检查adapter.notifyDataSetChanged();是否在主线程执行;


我遇到的情况是我在handle里面执行更新操作还是会出现上面那个错误,而且只是偶尔报错。


private Handler myHandler = new Handler(new Callback() {







@Override



public boolean handleMessage(Message msg) {




switch (msg.what) {




case Constant.MSG_SUCCESS:



if (adapter != null) {




adapter.notifyDataSetChanged();



}



break;



default:



break;



}



return false;



}



});


后来再网上查资料说handle不一定会在主线程。又改成这样:


private Handler myHandler = new Handler(new Callback() {







@Override



public boolean handleMessage(Message msg) {




switch (msg.what) {




case Constant.MSG_SUCCESS:



if (adapter != null) {




runOnUiThread(new Runnable() {




@Override



public void run() {




adapter.notifyDataSetChanged();



}



});



}



break;



default:



break;



}



return false;



}



});


还是会报错;后来想了很久发现问题原因,举个简单的例子


new Thread(new Runnable() {







@Override



public void run() {




// TODO Auto-generated method stub



for(int i = 0; i < 10; i++){




String str = “s”+i;



list.add(str);



}



myHandler.sendEmptyMessage(Constant.MSG_SUCCESS);



}



}).start();


list是adapter传递的集合数据是个全局变量。我们在子线程直接这样添加数据数量改变了有时候系统会自动更新ui导致报错。



只要改成这样就好了:



new Thread(new Runnable() {







@Override



public void run() {




// TODO Auto-generated method stub



List<String>listTemp = new ArrayList<String>();



for(int i = 0; i < 10; i++){




String str = “s”+i;



listTemp.add(str);



}



Message msg = Message.obtain();



msg.obj = listTemp;



msg.what = Constant.MSG_SUCCESS;



myHandler.sendMessage(msg);



}



}).start();








private Handler myHandler = new Handler(new Callback() {







@Override



public boolean handleMessage(Message msg) {




switch (msg.what) {




case Constant.MSG_SUCCESS:



list.addAll((List<String>)msg.obj);



if (adapter != null) {




adapter.notifyDataSetChanged();



}



break;



default:



break;



}



return false;



}



});








这样我们把添加数据都放在主线程,这就万无一失了



版权声明:本文为qq_24543821原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。