Java Android:IllegalStateException - 何时抛出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3353023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: IllegalStateException - When is it thrown?
提问by
In my application, sometimes the following exception is thrown:
在我的应用程序中,有时会抛出以下异常:
07-28 14:49:25.398: ERROR/AndroidRuntime(8097):
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(2131099717, class android.widget.ListView) with
Adapter(class ch.uzh.csg.games4blue.gamebase.view.UserView$UserAdapter)]
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.ListView.layoutChildren(ListView.java:1432)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.AbsListView.onLayout(AbsListView.java:1113)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.View.layout(View.java:6831)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.onLayout(LinearLayout.java:918)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.View.layout(View.java:6831)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1108)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.onLayout(LinearLayout.java:920)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.View.layout(View.java:6831)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.FrameLayout.onLayout(FrameLayout.java:333)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.View.layout(View.java:6831)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.onLayout(LinearLayout.java:918)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.View.layout(View.java:6831)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.LinearLayout.onLayout(LinearLayout.java:918)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.View.layout(View.java:6831)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.FrameLayout.onLayout(FrameLayout.java:333)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.View.layout(View.java:6831)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.widget.FrameLayout.onLayout(FrameLayout.java:333)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.View.layout(View.java:6831)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.ViewRoot.performTraversals(ViewRoot.java:996)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.os.Handler.dispatchMessage(Handler.java:99)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.os.Looper.loop(Looper.java:123)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
android.app.ActivityThread.main(ActivityThread.java:4338)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
java.lang.reflect.Method.invokeNative(Native Method)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
java.lang.reflect.Method.invoke(Method.java:521)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
07-28 14:49:25.398: ERROR/AndroidRuntime(8097): at
dalvik.system.NativeStart.main(Native Method)
It's difficult to find the error, because in the stacktrace none of my methods is listed. So, does anyone know when this exception is thrown? Thanks for any hints.
很难找到错误,因为在堆栈跟踪中没有列出我的任何方法。那么,有谁知道什么时候抛出这个异常?感谢您的任何提示。
采纳答案by Michael B.
You can see the error in your stacktrace :
您可以在堆栈跟踪中看到错误:
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.
适配器的内容已更改,但 ListView 未收到通知。确保适配器的内容不是从后台线程修改的,而只是从 UI 线程修改的。
You should look into one of your thread and make it synchronized with your UI thread.
您应该查看您的线程之一并使其与您的 UI 线程同步。
The way to do this in Android is with Handler.
在 Android 中执行此操作的方法是使用 Handler。
http://developer.android.com/guide/appendix/faq/commontasks.html#threading
http://developer.android.com/guide/appendix/faq/commontasks.html#threading
回答by JRL
Where you are using ch.uzh.csg.games4blue.gamebase.view.UserView$UserAdapter
.
你在哪里使用ch.uzh.csg.games4blue.gamebase.view.UserView$UserAdapter
.
回答by Sephy
Indeed, this kind of error is sent when you modify the content of your adapter, without notifying your listview or any other view using an adapter that its content should be updated.
Try to call .notifyDataSetChanged()
on the adapter.
实际上,当您修改适配器的内容时会发送这种错误,而不会通知您的列表视图或使用适配器的任何其他视图应该更新其内容。
尝试调用.notifyDataSetChanged()
适配器。
回答by Hamy
It does tell you the class the error occurs in: ch.uzh.csg.games4blue.gamebase.view.UserView
contains a class called UserAdapter
inside of it.
它确实会告诉您发生错误的类:ch.uzh.csg.games4blue.gamebase.view.UserView
包含在其中调用的类UserAdapter
。
Let me try to explain what is happening here - When you create a ListView
with an Adapter
backing it up, the ListView
gets its data by asking the adapter for it. Every time you scroll, the ListView is asking the Adapter for the new items that you scrolled into.
让我试着解释一下这里发生-当你创建一个ListView
与Adapter
在备份时,ListView
通过询问适配器它得到它的数据。每次滚动时,ListView 都会向适配器询问您滚动到的新项目。
Normally you create the ListView, you create the Adapter, you set the adapter on the listview, and you are done. Android OS takes care of the rest. What you are attempting to do, however, is a bit more complicated. You are trying to occasionally update the data in the adapter. You can imagine that the listview would need to be informed if the adapter data changed, right? If you are displaying a list with 2 items, and you suddenly add 2 more items to the adapter, then the list should now be displaying 4 items! However, it would be really inefficient if the listview had to be continually checking to see if the adapter has changed, right? So what needs to happen is the listview will assume that the adapter doesn't change, and the adapter will notify the listview if it does change. (This agreement between the listview and the adapter allows other benefits, such as the listview can cache some of the items retrieved from the adapter for quick access. Aka if there are 10 list items displayed on the screen, the list may have actually already requested 14 items. That way if you scroll up or down, for at least 2 items in either direction the ListView already has the data to display!)
通常,您创建 ListView、创建适配器、在列表视图上设置适配器,然后就完成了。Android 操作系统负责其余的工作。但是,您尝试执行的操作要复杂一些。您正在尝试偶尔更新适配器中的数据。您可以想象,如果适配器数据发生变化,列表视图将需要得到通知,对吗?如果您正在显示一个包含 2 个项目的列表,并且您突然向适配器添加了 2 个项目,那么该列表现在应该显示 4 个项目!但是,如果列表视图必须不断检查以查看适配器是否已更改,那将是非常低效的,对吗?所以需要发生的是,listview 将假设适配器没有改变,如果它确实发生了变化,适配器将通知 listview。
What you have failed to do, however, is to notify the listview that the data inside of the adapter changed. Somewhere inside UserAdapter or UserView the data is being changed! To make this easy on everyone, perhaps you could post the full UserView class? My bet is that you have some data object such as an ArrayList, as a private variable inside of the UserView class. Inside of the UserAdapter class you are providing this data to the ListView. However, somewhere inside of the UserView class you are modifying this dataset, afteryou have already provided it to the ListView.
但是,您没有做的是通知列表视图适配器内部的数据已更改。UserAdapter 或 UserView 内部的某处数据正在更改!为了让每个人都容易理解,也许您可以发布完整的 UserView 类?我敢打赌,您有一些数据对象(例如 ArrayList)作为 UserView 类中的私有变量。在 UserAdapter 类中,您将此数据提供给 ListView。但是,在 UserView 类内部的某个地方,您正在修改此数据集,之后您已将其提供给 ListView。
Disclaimer: I'm mostly copying other answers here, but I think I can provide a more clear view of what is happening if I combine the 2-3 answers given
免责声明:我主要在这里复制其他答案,但我认为如果我结合给出的 2-3 个答案,我可以更清楚地了解正在发生的事情
Disclaimer 2: I'm tired and this seems poorly written. Making it a wiki in the hopes someone cleans up my late night mess. If this is totally unintelligible just say so and ill delete it
免责声明 2:我很累,这似乎写得不好。把它变成一个维基,希望有人能帮我清理深夜的烂摊子。如果这完全无法理解,就说出来,然后删除它
回答by DroidBot
I have the same problem that you faced I was using asynchrousTask to fill data in listview.I solved by rewriting code that updates Ui in fn
我遇到了你遇到的同样问题,我使用 asynchrousTask 在 listview 中填充数据。我通过重写更新 fn 中的 Ui 的代码解决了
- onPostExecute()
- onPreExecute()
- 后执行()
- 预执行()
Because these function runs in UI thread.
因为这些函数在 UI 线程中运行。
Hope this helps.
希望这可以帮助。
回答by albnok
I just fixed this!
我刚刚修复了这个!
Previously I was doing heavy processing like this, where list
was static and under the Activity class:
以前我正在做这样的繁重处理,list
静态和活动类下的位置:
@Override
protected Void doInBackground(Void... arg0) {
for (int i=0; i<bigChunk.size(); i++) {
list.add(somethingHeavy(i));
}
}
I then made a new list, and added it in:
然后我创建了一个新列表,并将其添加到:
List<YourObject> listToAdd;
@Override
protected Void doInBackground(Void... arg0) {
listToAdd = new ArrayList<YourObject>();
for (int i=0; i<bigChunk.size(); i++) {
listToAdd.add(somethingHeavy(i));
}
}
@Override
protected void onPostExecute(Void result) {
list = listToAdd;
adapter.notifyDataSetChanged();
}