房间出现 ConcurrentModificationException

Nav*_*oid 2 android android-sqlite android-room

我在将数据插入 Android 表时遇到问题。这是我的 Dao 函数:

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(freight: Foo)

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(freights: MutableList<Foo>)
Run Code Online (Sandbox Code Playgroud)

下面是它的调用方式:

  Observable.fromCallable {
          db.fooDao().insert(it)
       }
    }
            .subscribeOn(Schedulers.io())
            .observeOn(Schedulers.io())
            .subscribe {
                Logger.d("Inserted ${it} users from API in DB...")
            }
Run Code Online (Sandbox Code Playgroud)

我得到的异常:

   Caused by: java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.next(ArrayList.java:860)
    at com.blockgrain.blockgrain.dbmanager.repository.FooRepository$insertDataInDb$1.call(FooRepository.kt:76)
Run Code Online (Sandbox Code Playgroud)

我已经创建了具有相同逻辑的其他表,它们工作正常,但这个失败了。请让我知道出了什么问题。

更新

Foo.kt

 override fun get(): Observable<MutableList<Foo>> {
    val observable = getDataFromDb()
    return observable.flatMap {
        if (it.isEmpty())
            getDataFromApi()
        else
            observable
    }
}

override fun getDataFromApi(): Observable<MutableList<Foo>> {

    return WebService.createWithAuth().getFooFromWeb()
            .doOnNext {
                Logger.d(" Dispatching ${it} users from API...")
                Observable.fromCallable {
                     db.fooDao().insert(it)
                      }
                  }
                  .subscribeOn(Schedulers.io())
                  .observeOn(Schedulers.io())
                  .subscribe {
                           Logger.d("Inserted ${it} users from API in DB...")
                  }
               }
}
Run Code Online (Sandbox Code Playgroud)

adi*_*e49 6

根据给定的代码,目前尚不清楚如何调用数组列表修改,从而生成Caused by: java.util.ConcurrentModificationException. 我的猜测是,一次对同一个列表执行多个操作。

您在 dao 中的插入列表方法接受MutableList<Foo>将其更改为,List<Foo>因为 Room 不需要可变列表。像这样,

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(freights: List<Foo>)
Run Code Online (Sandbox Code Playgroud)

我建议在对列表执行任何操作之前将数组列表复制另一个列表

// Before performing any operation on list
var newList:List<Foo> = ArrayList<Foo>(otherList)
// Perform operation on newList - for ex.
db.insert(newList)
Run Code Online (Sandbox Code Playgroud)

如果您想与CopyOnWriteArrayListArrayList同时使用它,还有另一种解决方案。但这将导致现有代码发生重大修改。所以我建议选择第一个选项。