【问题标题】:Room getting ConcurrentModificationException房间得到 ConcurrentModificationException
【发布时间】:2018-07-16 07:06:23
【问题描述】:

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

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

【问题讨论】:

  • 你在这里调用哪种方法db.fooDao().insert(it) 用于单个元素或Foo 列表?
  • 我尝试了单一和列表..都失败了同样的异常
  • 您确定没有在访问列表的同时修改列表吗?你能分享FooRepository.kt:76的代码吗?
  • 为 FooRepository 添加了代码。异常在 db.fooDao().insert(it)
  • 您是否尝试使用此代码插入多个项目?

标签: android android-sqlite android-room


【解决方案1】:

根据给定的代码,不直接明确如何调用数组列表修改导致 Caused by: java.util.ConcurrentModificationException 。 我的猜测是,一次在同一个列表上执行多个操作。

您在 dao 中的插入列表方法接受 MutableList&lt;Foo&gt; 将其更改为 List&lt;Foo&gt;,因为 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,还有另一种解决方案。但这将导致对现有代码的重大修改。所以我建议选择第一个选项。

【讨论】:

  • 这行得通,但另一方面,我仍然对列表的使用位置感到困惑。无论如何,谢谢..
  • 很高兴它有帮助。您可能需要调试您的代码以找到它同时使用的位置,因为代码是反应性的,我们无法直接确定它
猜你喜欢
  • 2018-11-17
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多