房间正在获取ConcurrentModificationException

时间:2018-07-16 07:06:24

标签: android android-sqlite android-room

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

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

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(freights: MutableList<Foo>)

这里是调用方式:

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

我得到的异常:

   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)

我用相同的逻辑创建了其他表,它们工作正常,但是此表失败了。请让我知道出了什么问题。

更新

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...")
                  }
               }
}

1 个答案:

答案 0 :(得分:1)

按照给定的代码,不直接清楚是如何调用数组列表修改而导致Caused by: java.util.ConcurrentModificationException的。 我的猜测是,一次对同一列表执行多项操作。

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

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(freights: List<Foo>)

我建议先将数组列表复制到另一个列表,然后再对列表进行任何操作

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

如果要与CopyOnWriteArrayList同时使用ArrayList,还有另一种解决方案。但这将导致代码中现有内容的重大修改。因此,我建议选择第一个选项。