安卓:IllegalStateException - 什么时候抛出?

13

在我的应用程序中,有时会抛出以下异常:

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)

很难找到错误,因为在堆栈跟踪中没有列出我的任何方法。那么,有人知道何时抛出此异常吗?感谢任何提示。

6个回答

24

它确实告诉你错误发生的类:ch.uzh.csg.games4blue.gamebase.view.UserView 包含了一个叫做 UserAdapter 的类。

让我试着解释一下这里发生了什么 - 当你创建一个 ListView 并使用一个支持它的 AdapterListView 会通过请求适配器来获取数据。每次滚动时,ListView 都会向适配器请求新的滚动项。

通常情况下,你创建 ListView,创建 Adapter,将 Adapter 设置到 listview 上,然后就完成了。Android 操作系统会处理剩下的事情。但是,你正试图完成一些更加复杂的任务。你正在尝试定期更新适配器中的数据。你可以想象一下,如果适配器的数据发生变化,listview 就需要被通知,对吧?如果你正在显示一个包含2个项目的列表,然后你突然向适配器添加了2个项目,那么列表现在应该显示4个项目!但是,如果 listview 不断检查适配器是否已经改变,那就非常低效了,对吧?所以需要发生的是,listview 会假设适配器不会改变,并且适配器会在其发生变化时通知 listview。(这种 listview 和适配器之间的协议还允许其他好处,例如 listview 可以将一些从适配器检索出的项目缓存起来以便快速访问。也就是说,如果屏幕上显示了10个列表项,则列表实际上可能已经请求了14个项目。这样,如果你向上或向下滚动,对于任何方向至少有 2 个项目,ListView 已经具有显示数据的数据!)

然而,你没有通知列表视图适配器内部数据已经改变。用户适配器或用户视图内的某个地方正在更改数据!为了让每个人都能轻松理解,也许你可以发布完整的UserView类?我猜你在UserView类的私有变量中拥有一些数据对象,例如ArrayList。在UserAdapter类中,你将此数据提供给ListView。但是,在你已经将其提供给ListView之后,可能在UserView类的某个地方修改了这个数据集。

免责声明:我大部分是在复制其他答案,但是如果我结合2-3个答案给出一个更清晰的视角,我认为我可以提供更清晰的视角。

免责声明2:我很累,这篇文章似乎写得很差。我把它做成了一个维基百科,希望有人能整理我的深夜糊涂。如果这完全无法理解,请告诉我,我会删除它。


4
你可以在堆栈跟踪中看到错误:

适配器的内容已更改,但ListView未收到通知。确保您的适配器的内容不是从后台线程修改的,而是仅从UI线程修改。

您应该查看其中一个线程,并将其与UI线程同步。

在Android中执行此操作的方法是使用Handler。

http://developer.android.com/guide/appendix/faq/commontasks.html#threading


Michael B. 我需要你的帮助,事实上我也遇到了同样的错误。这是问题的链接:http://stackoverflow.com/questions/16477755/application-stops-on-changing-page - user2134412

2

当你使用ch.uzh.csg.games4blue.gamebase.view.UserView$UserAdapter时。


1

实际上,当您修改适配器的内容时,如果没有通知使用适配器的任何其他视图或列表视图其内容应该更新,则会发送此类错误。
尝试在适配器上调用.notifyDataSetChanged()


1

我有和你一样的问题,我正在使用asynchrousTask在listview中填充数据。我通过重写更新UI的fn代码来解决了这个问题。

  1. onPostExecute()
  2. onPreExecute()

因为这些函数在UI线程中运行。

希望这能帮到你。


0

我刚刚修复了这个问题!

以前我一直在进行类似于这样的重型处理,其中list是静态的并且在Activity类下:

@Override
protected Void doInBackground(Void... arg0) {
    for (int i=0; i<bigChunk.size(); i++) {
        list.add(somethingHeavy(i));
    }
}

然后我创建了一个新的列表,并将其添加进去:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接