android-LV数据源初始化异常

来源:互联网 发布:阿里云 搭建lamp 编辑:程序博客网 时间:2024/05/06 08:00

解决java.lang.IllegalStateException: The content of the adapter has changed but ListView…的问题
分类: Android 2014-03-06 09:47 10104人阅读 评论(4) 收藏 举报
androidadapterUI thread
我写了一个Dialog,Dialog中有一个ListView,想要点ListView中的一项后,跳转到另外一个Activity去。

但在使用时,会偶尔报出下面的错误:

02-21 14:54:28.928: E/AndroidRuntime(2846): FATAL EXCEPTION: main

02-21 14:54:28.928: E/AndroidRuntime(2846): 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. [in ListView(2131165196, class android.widget.ListView) with Adapter(class com.jovision.multiscreen.views.DeviceScanSelectDialogDeviceAdapter)]022114:54:28.928:E/AndroidRuntime(2846):atandroid.widget.ListView.layoutChildren(ListView.java:1510)022114:54:28.928:E/AndroidRuntime(2846):atandroid.widget.AbsListView.onTouchModeChanged(AbsListView.java:2077)022114:54:28.928:E/AndroidRuntime(2846):atandroid.view.ViewTreeObserver.dispatchOnTouchModeChanged(ViewTreeObserver.java:591)022114:54:28.928:E/AndroidRuntime(2846):atandroid.view.ViewRoot.ensureTouchModeLocally(ViewRoot.java:2095)022114:54:28.928:E/AndroidRuntime(2846):atandroid.view.ViewRoot.performTraversals(ViewRoot.java:809)022114:54:28.928:E/AndroidRuntime(2846):atandroid.view.ViewRoot.handleMessage(ViewRoot.java:1861)022114:54:28.928:E/AndroidRuntime(2846):atandroid.os.Handler.dispatchMessage(Handler.java:99)022114:54:28.928:E/AndroidRuntime(2846):atandroid.os.Looper.loop(Looper.java:130)022114:54:28.928:E/AndroidRuntime(2846):atandroid.app.ActivityThread.main(ActivityThread.java:3683)022114:54:28.928:E/AndroidRuntime(2846):atjava.lang.reflect.Method.invokeNative(NativeMethod)022114:54:28.928:E/AndroidRuntime(2846):atjava.lang.reflect.Method.invoke(Method.java:507)022114:54:28.928:E/AndroidRuntime(2846):atcom.android.internal.os.ZygoteInitMethodAndArgsCaller.run(ZygoteInit.java:895)
02-21 14:54:28.928: E/AndroidRuntime(2846): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:653)
02-21 14:54:28.928: E/AndroidRuntime(2846): at dalvik.system.NativeStart.main(Native Method)

其中错误描述:

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的内容变化了,但是你的ListView并不知情。请保证你adapter的数据在主线程中进行更改!

知道了原因,改起来就好办多了,我将我的adapter类改为:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
private class DeviceAdapter extends BaseAdapter {

private LayoutInflater inflater;  private ArrayList<Device> devices;  public DeviceAdapter() {      inflater = LayoutInflater.from(mContext);  }  @SuppressWarnings("unchecked")  public void setDeviceList(ArrayList<Device> list) {      if (list != null) {          devices = (ArrayList<Device>) list.clone();          notifyDataSetChanged();      }  }  public void clearDeviceList() {      if (devices != null) {          devices.clear();      }      notifyDataSetChanged();  }  @Override  public int getCount() {      return devices == null ? 0 : devices.size();  }  

以下略)
相对于原来,我做了两项改动:

1.将所有数据“完全”保存在adapter内部,即使有外部数据进入,也会用.clone()重新生成副本,保证了数据完全是由adapter维护的。

2.保证所有setDeviceList()/clearDeviceList()是从主线程里调用的,如何保证是从主线程中调用的呢:

  a.调用Activity.runOnUIThread()方法;

  b.使用Handler(其实这并不非常准确,因为Handler也可以运行在非UI线程);

  c.使用AsyncTask。

希望能帮到遇到同样问题的同学~

0 0