Pierre Rymiortz
Pierre Rymiortz

Reputation: 1127

ConcurrentModificationException crashes my app

My Android app has an IntentService where it requests a list of MessageThreads objects from Facebook, parses the JSON response to build an ArrayList of the objects:

ArrayList<MessageThread> mMessageThreads = new ArrayList<MessageThread>();

Then it calls FB again in the same service, get the names for the MessageThread ids and matches them with the MessageThread objects. At this point I have an ArrayList with complete MessageThread objects and I insert them into an SQLite db.

// save to db and broadcast
for (MessageThread message : mMessageThreads) {
    ((FBClientApplication)getApplication()).getMessagesData().insertOrIgnore(message.toContentValues();
}

where:

public void insertOrIgnore(ContentValues values) {
    SQLiteDatabase db = this.dbHelper.getWritableDatabase();
    db.insertWithOnConflict(TABLE, null, values, SQLiteDatabase.CONFLICT_IGNORE);
}

Via ACRA reports I see that intermittently the line

for (MessageThread message : mMessageThreads) 

throws an ConcurrentModificationException and the app forcloses. I haven't been able to isolate under what conditions. I read about this Exception and as I understand it it happens when we remove items from an ArrayList while iterating over it, but I'm not removing items from the list. Any pointers to help with this problem are greatly appreciated.

Upvotes: 0

Views: 201

Answers (2)

Hector Romero
Hector Romero

Reputation: 262

What you can try to do is when you iterates your Collection instead of using the original you can make a copy right there, so you will have something like:

for (MessageThread message : new List<MessageThread>(mMessageThreads))

That will help you to avoid CuncurrentModificationException. Now if you really want to get fancy you can protect your code using synchronized blocks such as:

synchronized(mMessageThreads){
    for (MessageThread message : new List<MessageThread>(mMessageThreads)){
    ...
}

With this last pice of code you will restrict the access to mMessageThreads, if somebody it's using it it will get locked, so if somebody else wants to use it needs to wait until the first one is done.

Upvotes: 2

Louis Wasserman
Louis Wasserman

Reputation: 198014

It also happens when you add items to an ArrayList while iterating over it, which it looks like you might do in this code.

In general, it's any "structural modification" that occurs to the ArrayList that can cause a CME while iterating.

Upvotes: 2

Related Questions