Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: Jayesh Salvi <jayeshsalvi <at> gmail.com>
Subject: IllegalStateException after ListView's adapter has changed
Newsgroups: gmane.comp.handhelds.android.devel
Date: Monday 22nd February 2010 07:31:40 UTC (over 6 years ago)
Hi,

This is regarding the exception:  "java.lang.IllegalStateException: The
content of the adapter has changed but ListView did not receive a
notification....." - seen on Android 1.6+

This problem has been discussed in the past [1][2][3][4], and I have
followed all the solutions suggested in those threads. However, few of my
users still hit this crash. So I did some source code lookup and have some
questions.

Here is the description of what my app is doing:

I use a ListView and populate it with an adapter. The adapter is a direct
derivative of BaseAdapter. I populate the list progressively. As the items
are downloaded from network they get added to the adapter. The fetching of
items is done in doInBackground() and when they are ready to get added to
the adapter I invoke publishProgress(), in the onProgressUpdate() method I
add new items one-by-one to the adapter. As soon as I add the item to the
adapter, I invoke notifyDataSetChanged().

I believe this is as per the best practices that Android developers have
suggested in above mentioned threads.

Despite this I get crash reports with this exception. They are rare, but
not
as rare as ignorable. I myself have hit this crash on my phone/emulator
only
1-2 times in last couple of months. The user reported crashes are roughly 1
to 3 per day (approx. at least 600 users use the app per day) (A minority
of
users may be hitting this crash over and over again)
. This leads me to believe that my adapter update logic is mostly right,
but
not full proof.

So I dug into the source code of ListView and BaseAdapter.

The exception is thrown because ListView's mItemCount doesn't match the
underlying adapter's item count. It happens in layoutChildren()
[ListView.java
line 1432<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/widget/ListView.java;h=7c8151e65132a91aecadd2048fe205bd1c6768a9;hb=HEAD#l1431>
]
....
             } else if (mItemCount != mAdapter.getCount()) {
                throw new IllegalStateException("The content of the adapter
has changed but "
                        + "ListView did not receive a notification. Make
sure the content of "
....

So in order to avoid this from happening mItemCount should be updated as
soon as the adapter has changed its content. So I searched for locations in
the code where mItemCount is updated. I found two locations doing that. In
setAdapter() [ListView.java
431<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/widget/ListView.java;h=7c8151e65132a91aecadd2048fe205bd1c6768a9;hb=HEAD#l431>]
and in onMeasure() [ListView.java
1033<http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/widget/ListView.java;h=7c8151e65132a91aecadd2048fe205bd1c6768a9;hb=HEAD#l1033>].
Consequently, if I am updating the adapter then either setAdapter() or
onMeasure() should be executed before the comparision in layoutChildren()
takes place, otherwise the exception will be thrown.

My question is, is it possible that my code in onProgressUpdate() that
appends to adapter can get executed between onMeasure() and
layoutChildren()
of the ListView? AFAIU, all three of these methods (onProgressUpdate,
onMeasure, layoutChildren) run on the same GUI thread.

I call notifyDataSetChanged immediately after I add to adapter in
onProgressUpdate(). I looked into its source code. It calls methods on
DataSetObservable and DataSetObserver. I couldn't find how it could
directly
lead to the updating of mItemCount of the ListView, clearly I don't know
much of the internal layout code.

Please let me know what you think. I am trying to understand this mechanism
as thoroughly as possible.

Thanks in advance.

Links:
[1]
http:[email protected]/msg60355.html
[2]
http:[email protected]/msg65814.html
[3]
http://groups.google.com/group/android-developers/browse_thread/thread/77722caa85f87697
[4]
http://groups.google.com/group/android-developers/browse_thread/thread/a451221261cb6a93/2ab5bea015c38437?lnk=gst&q=For+Google+about+BaseAdapter+class#2ab5bea015c38437
[5] ListView.java source code I refered to:
http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/widget/ListView.java;h=7c8151e65132a91aecadd2048fe205bd1c6768a9;hb=HEAD

--
Jayesh

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
 
CD: 2ms