adapter的数据应该在主线程中进行更改

来源:互联网 发布:泸州广电网络客服电话 编辑:程序博客网 时间:2024/05/14 18:15

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.DeviceScanSelectDialog$DeviceAdapter)]
02-21 14:54:28.928: E/AndroidRuntime(2846):     at android.widget.ListView.layoutChildren(ListView.java:1510)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at android.widget.AbsListView.onTouchModeChanged(AbsListView.java:2077)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at android.view.ViewTreeObserver.dispatchOnTouchModeChanged(ViewTreeObserver.java:591)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at android.view.ViewRoot.ensureTouchModeLocally(ViewRoot.java:2095)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at android.view.ViewRoot.performTraversals(ViewRoot.java:809)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1861)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at android.os.Looper.loop(Looper.java:130)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at android.app.ActivityThread.main(ActivityThread.java:3683)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at java.lang.reflect.Method.invokeNative(Native Method)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at java.lang.reflect.Method.invoke(Method.java:507)
02-21 14:54:28.928: E/AndroidRuntime(2846):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.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上查看代码片派生到我的代码片
  1. private class DeviceAdapter extends BaseAdapter {  
  2.   
  3.     private LayoutInflater inflater;  
  4.     private ArrayList<Device> devices;  
  5.   
  6.     public DeviceAdapter() {  
  7.         inflater = LayoutInflater.from(mContext);  
  8.     }  
  9.   
  10.     @SuppressWarnings("unchecked")  
  11.     public void setDeviceList(ArrayList<Device> list) {  
  12.         if (list != null) {  
  13.             devices = (ArrayList<Device>) list.clone();  
  14.             notifyDataSetChanged();  
  15.         }  
  16.     }  
  17.   
  18.     public void clearDeviceList() {  
  19.         if (devices != null) {  
  20.             devices.clear();  
  21.         }  
  22.         notifyDataSetChanged();  
  23.     }  
  24.   
  25.     @Override  
  26.     public int getCount() {  
  27.         return devices == null ? 0 : devices.size();  
  28.     }  
  29. 以下略)  

相对于原来,我做了两项改动:

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

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

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

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

  c.使用AsyncTask。


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

0 0
原创粉丝点击