Javaを解決します.lang.IllegalStateException: The content of the adapter has changed but ListView...の質問
3615 ワード
私はDialogを書きました.DialogにはListViewがあります.ListViewの1つを注文したい後、別の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.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クラスを次のように変更しました.
従来に比べて、私は2つの変更をしました.
1.すべてのデータを「完全」にadapter内部に保存する、外部データが入っても使用する.clone()はレプリカを再生成し、データが完全にadapterによって維持されることを保証します.
2.すべてのsetDeviceList()/clearDeviceList()がプライマリスレッドから呼び出されたことを保証します.プライマリスレッドから呼び出されたことをどのように保証しますか.
a.Activity.を呼び出すrunOnUIthread()メソッド;
b.Handlerを使用する(実際にはこれは非常に正確ではない.Handlerは非UIスレッドでも実行できるからである);
c.AsyncTaskを使用する.
同じ問題に遭遇した同級生を助けてほしい.
しかし、使用時には、次のエラーがたまに報告されます.
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クラスを次のように変更しました.
private class DeviceAdapter extends BaseAdapter {
private LayoutInflater inflater;
private ArrayList devices;
public DeviceAdapter() {
inflater = LayoutInflater.from(mContext);
}
@SuppressWarnings("unchecked")
public void setDeviceList(ArrayList list) {
if (list != null) {
devices = (ArrayList) list.clone();
notifyDataSetChanged();
}
}
public void clearDeviceList() {
if (devices != null) {
devices.clear();
}
notifyDataSetChanged();
}
@Override
public int getCount() {
return devices == null ? 0 : devices.size();
}
( )
従来に比べて、私は2つの変更をしました.
1.すべてのデータを「完全」にadapter内部に保存する、外部データが入っても使用する.clone()はレプリカを再生成し、データが完全にadapterによって維持されることを保証します.
2.すべてのsetDeviceList()/clearDeviceList()がプライマリスレッドから呼び出されたことを保証します.プライマリスレッドから呼び出されたことをどのように保証しますか.
a.Activity.を呼び出すrunOnUIthread()メソッド;
b.Handlerを使用する(実際にはこれは非常に正確ではない.Handlerは非UIスレッドでも実行できるからである);
c.AsyncTaskを使用する.
同じ問題に遭遇した同級生を助けてほしい.