I recieve exception while manipulating with navigation forward and backward from FragmentActivity, containing ListView with data loaded from custom Loader (it is loading from local sqlite database), and do not know how to deal with it...
Here is a stacktrace:
Uncaught exception: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.PriceTracerActivity}: java.lang.RuntimeException: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.CartFragmentActivity}: java.util.ConcurrentModificationException
java.lang.RuntimeException: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.PriceTracerActivity}: java.lang.RuntimeException: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.CartFragmentActivity}: java.util.ConcurrentModificationException
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3106)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3171)
at android.app.ActivityThread.access$2100(ActivityThread.java:132)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1071)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:4293)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.CartFragmentActivity}: java.util.ConcurrentModificationException
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3106)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:2994)
at android.app.LocalActivityManager.dispatchDestroy(LocalActivityManager.java:625)
at android.app.ActivityGroup.onDestroy(ActivityGroup.java:85)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3088)
... 11 more
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:576)
at android.database.DataSetObservable.notifyInvalidated(DataSetObservable.java:42)
at android.widget.BaseAdapter.notifyDataSetInvalidated(BaseAdapter.java:54)
at android.support.v4.widget.CursorAdapter.swapCursor(CursorAdapter.java:352)
at com.snyer.bestprice.CartFragmentActivity.onLoaderReset(CartFragmentActivity.java:412)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.destroy(LoaderManager.java:337)
at android.support.v4.app.LoaderManagerImpl.doDestroy(LoaderManager.java:773)
at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:318)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3088)
... 15 more
Exceptions occures at line mCartCursorAdapter.swapCursor(null);
of this code-fragment (CartFragmentActivity.java:412):
public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()) {
case LOADER_CART_LIST_ID:
mCartListCursorAdapter.swapCursor(null);
break;
case LOADER_CART_CONTENTS_ID:
mCartCursorAdapter.swapCursor(null);
break;
}
}
What can be done here to remove this exception?
The sdk source gives a good hint as a comment:
In Android 4.0.4 it is:
public void notifyInvalidated() {
synchronized(mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onInvalidated();
}
}
}
In earlier versions it was:
synchronized (mObservers) {
for (DataSetObserver observer : mObservers) {
observer.onInvalidated();
}
}
The 4.0.4 source has the following comment regarding the same changes in onChange method:
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
I am not aware of manipulating the ArrayList of observers in any illegal way though. Since this is solved in later APIs and I can't think of any impact on my App I think I am simply going to ignore the exception with a log entry or similar.