0

我的 Android 应用程序有一个 IntentService,它从 Facebook 请求 MessageThreads 对象列表,解析 JSON 响应以构建对象的 ArrayList:

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

然后它在同一个服务中再次调用 FB,获取 MessageThread id 的名称并将它们与 MessageThread 对象匹配。此时,我有一个包含完整 MessageThread 对象的 ArrayList,并将它们插入到 SQLite 数据库中。

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

在哪里:

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

通过 ACRA 报告,我间歇性地看到这条线

for (MessageThread message : mMessageThreads) 

抛出一个ConcurrentModificationException并且应用程序关闭。我一直无法在什么条件下隔离。我读到了这一点Exception,据我了解,当我们ArrayList在迭代它时删除项目时会发生这种情况,但我没有从列表中删除项目。非常感谢任何有助于解决此问题的指针。

4

2 回答 2

2

当您在迭代它时添加项目时也会发生这种情况ArrayList,看起来您可以在此代码中执行此操作。

一般来说,ArrayList在迭代过程中发生的任何“结构修改”都可能导致 CME。

于 2013-02-07T00:20:04.077 回答
2

您可以尝试做的是,当您迭代您的集合而不是使用原始集合时,您可以在那里制作副本,因此您将拥有类似的东西:

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

这将帮助您避免 CuncurrentModificationException。现在,如果您真的想变得花哨,可以使用同步块保护您的代码,例如:

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

使用这最后一段代码,您将限制对 mMessageThreads 的访问,如果有人使用它,它将被锁定,因此如果其他人想要使用它需要等到第一个完成。

于 2013-02-07T03:36:15.287 回答