Android 并发修改异常室

Nab*_*oft 6 java android android-room

我在我的应用程序中使用 Room,在将数据插入我的数据库时,ConcurrentModificationException有时会抛出错误。为什么会这样呢?

我使用分页 api,在每次 api 调用后,我使用以下命令将 dataList 插入到我的数据库中

new Thread(new Runnable() {
            @Override
            public void run() {                    
                    appDatabase.dataDao().insertMultipleData(dataList);                    
            }
        }).start();
Run Code Online (Sandbox Code Playgroud)

在哪里

appDatabase = Room.databaseBuilder(context, AppDatabase.class, AppDatabase.DATABASE_NAME)
                .fallbackToDestructiveMigration()
                .build();
Run Code Online (Sandbox Code Playgroud)

插入操作

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertMultipleData(List<Data> dataList);
Run Code Online (Sandbox Code Playgroud)

Aji*_*ana 2

如果您尝试在分页列表中插入数据,这是一个典型的场景。由于您尚未粘贴错误日志,因此我假设错误是在 dataList 对象上引起的。在这种情况下,错误消息将如下所示。

 java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.next(ArrayList.java:860)
        at androidx.room.EntityInsertionAdapter.insertAndReturnIdsArray(EntityInsertionAdapter.java:131)
        at com.myApp.data.database.entities.FeedDataDao_Impl.insertAll(FeedDataDao_Impl.java:220)
Run Code Online (Sandbox Code Playgroud)

如果是这种情况,则错误是由不同线程并行修改同一变量引起的。在这种情况下,我假设您将数据插入数据库,同时执行新的服务调用(分页)以获取更新同一数据对象的数据。或者,即使在插入原始数组源时从原始数组源中删除内容,也可能会抛出此错误。解决方案非常简单。您可以将变量dataList复制到新变量,并使用新的局部变量作为插入调用的参数。

例如:(科特林)

val localCopy = dataList
CoroutineScope(Dispatchers.IO).launch {

        AppDatabase.getDatabase(context).feedDataDao().insertAll(localCopy).size

 }.invokeOnCompletion {
        Log.d("Inserted all items")
 }
Run Code Online (Sandbox Code Playgroud)

例如:(Java)

List<MyDataType> localCopy = dataList       
AppDatabase.getDatabase(context).feedDataDao().insertAll(localCopy).size
Run Code Online (Sandbox Code Playgroud)