I have a fix for this. Just set the visibility of ur ListView to Gone during update and back to visible after update. By doing so, u can avoid the inconsistency of ur adapter and listView item count.
On Mon, Feb 22, 2010 at 3:31 PM, Jayesh Salvi <jayeshsa...@gmail.com> wrote: > 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://www.mail-archive.com/android-developers@googlegroups.com/msg60355.html > [2] > http://www.mail-archive.com/android-developers@googlegroups.com/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 android-developers@googlegroups.com > To unsubscribe from this group, send email to > android-developers+unsubscr...@googlegroups.com<android-developers%2bunsubscr...@googlegroups.com> > For more options, visit this group at > http://groups.google.com/group/android-developers?hl=en -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en To unsubscribe, reply using "remove me" as the subject.