简体   繁体   English

Android:IllegalStateException-什么时候抛出?

[英]Android: IllegalStateException - When is it thrown?

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. 很难找到错误,因为在stacktrace中没有列出我的方法。 So, does anyone know when this exception is thrown? 那么,有人知道何时抛出该异常吗? Thanks for any hints. 感谢您的任何提示。

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.UserViewch.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. 让我试着解释这里发生了什么-当你创建一个ListViewAdapter进行备份时, ListView通过询问适配器它得到它的数据。 Every time you scroll, the ListView is asking the Adapter for the new items that you scrolled into. 每次滚动时,ListView都会向适配器询问您滚动到的新项目。

Normally you create the ListView, you create the Adapter, you set the adapter on the listview, and you are done. 通常,您创建ListView,创建适配器,在列表视图上设置适配器,然后完成。 Android OS takes care of the rest. 其余部分由Android OS负责。 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? 您可以想象如果适配器数据发生更改,则需要通知listview,对吗? 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! 如果您要显示包含2个项目的列表,而您突然将另外2个项目添加到适配器,那么该列表现在应该显示4个项目! However, it would be really inefficient if the listview had to be continually checking to see if the adapter has changed, right? 但是,如果必须不断检查listview以查看适配器是否已更改,那将是非常低效的,对吗? 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!) (列表视图和适配器之间的这种协议还带来了其他好处,例如列表视图可以缓存从适配器检索到的某些项目以进行快速访问。再者,如果屏幕上显示了10个列表项目,则该列表可能实际上已经被请求了。 14个项目。这样,如果您向上或向下滚动,则在任一方向上至少有2个项目,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! 在UserAdapter或UserView内部的某个位置,数据正在更改! To make this easy on everyone, perhaps you could post the full UserView class? 为了使每个人都容易做到这一点,也许您可​​以发布完整的UserView类? My bet is that you have some data object such as an ArrayList, as a private variable inside of the UserView class. 我敢打赌,您有一些数据对象(例如ArrayList)作为UserView类内部的私有变量。 Inside of the UserAdapter class you are providing this data to the ListView. 在UserAdapter类内部,您正在将此数据提供给ListView。 However, somewhere inside of the UserView class you are modifying this dataset, after you have already provided it to the ListView. 但是,在将UserData类提供给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. 免责声明2:我很累,这似乎写得不好。 Making it a wiki in the hopes someone cleans up my late night mess. 使其成为Wiki,希望有人能清理我的深夜混乱。 If this is totally unintelligible just say so and ill delete it 如果这完全无法理解,请说出并删除它

You can see the error in your stacktrace : 您可以在stacktrace中看到错误:

The content of the adapter has changed but ListView did not receive a notification. 适配器的内容已更改,但ListView没有收到通知。 Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. 确保不从后台线程修改适配器的内容,而仅从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

使用ch.uzh.csg.games4blue.gamebase.view.UserView$UserAdapter

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()

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的代码解决了

  1. onPostExecute() onPostExecute()
  2. onPreExecute() onPreExecute()

Because these function runs in UI thread. 因为这些功能在UI线程中运行。

Hope this helps. 希望这可以帮助。

I just fixed this! 我刚刚解决了这个问题!

Previously I was doing heavy processing like this, where list was static and under the Activity class: 以前,我像这样进行繁重的处理,其中list是静态的,并且在Activity类下:

@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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android:抛出IllegalStateException - Android: IllegalStateException thrown 在Android中为我的应用抛出IllegalStateException - IllegalStateException thrown for my app in Android Android:调用AppCompatActivity时抛出IllegalStateException - Android: IllegalStateException is thrown while calling AppCompatActivity 下载项目依赖项时,Maven抛出IllegalStateException(与SSL相关?) - IllegalStateException thrown by Maven (SSL-related?) when downloading project dependencies 尝试运行我的游戏启动器时抛出IllegalStateException - IllegalStateException thrown when trying to run my Game Launcher 删除SQLite表时出现IllegalStateException-Android - IllegalStateException when deleting SQLite table - Android 在某些设备上录制音频时,Android IllegalStateException - Android IllegalStateException when recording audio on some devices Android:执行单元测试时Android支持中的IllegalStateException - Android: IllegalStateException in Android Support when executing Unit Tests @PostConstruct中抛出的异常会导致JSF 2.1中出现IllegalStateException - Exception thrown in @PostConstruct causes IllegalStateException in JSF 2.1 尝试在Android中隐藏Linearlayouts时出现Java.lang.illegalstateexception - Java.lang.illegalstateexception when trying to hide Linearlayouts in Android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM