views:

83

answers:

4

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.

+2  A: 

Where you are using ch.uzh.csg.games4blue.gamebase.view.UserView$UserAdapter.

JRL
+1  A: 

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.

You should look into one of your thread and make it synchronized with your UI thread.

The way to do this in Android is with Handler.

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

Michael B.
+1  A: 

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.

Sephy
+1  A: 

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.

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.

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

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, after you have already provided it to the 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

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

Hamy