我的应用程序崩溃时进入横向模式,ConcurrentModificationException使用协程



我用我的布局中包含的所有视图创建了一个纵向布局的横向变化。

但是当我运行应用程序并旋转设备时,有一个崩溃的错误:

E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.user.project_name, PID: 15543
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at com.user.project_name.MainActivity$findSingleCountry$1.invokeSuspend(MainActivity.kt:157)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

这个错误指的是我的MainActivity上的这个代码:

private fun findSingleCountry(name: String) {
CoroutineScope(Dispatchers.Default).launch {
fiscalCode.birthPlace = "X999"
for (country in countryList) {
if (country.description.uppercase() == name.uppercase()) {
fiscalCode.birthPlace = country.code
break
}
}
cFViewModel.getFiscalCode(fiscalCode)
}
}
第157行是:for (country in countryList) {

我只在onCreate()中调用这个方法:

binding.acBirthCountry.setOnItemClickListener { adapterView, _, itemPos, _ ->
fiscalCode.birthPlace =  (adapterView.adapter.getItem(itemPos) as CountryModel).code
cFViewModel.getFiscalCode(fiscalCode)
}
binding.acBirthCountry.doAfterTextChanged { name ->
findSingleCountry(name.toString())
}

为什么我的应用程序只有在进入横向模式时才会崩溃?

编辑:

如何在主线程中不运行函数的情况下解决这个问题?

编辑:

根据文档:

注意,这个异常并不总是表明一个对象被另一个线程并发地修改了。如果单个线程发出的一系列方法调用违反了对象的契约,则该对象可能会抛出此异常。例如,如果线程在使用快速失败迭代器迭代该集合时直接修改了该集合,则迭代器将抛出此异常。

这个异常只是警告代码可能违反了对象的契约,实际上,当设备切换到横向模式时,方法findSingleCountry不会被调用。

当我进入横向模式时忽略异常是这种情况吗?

问题很可能在于集合countryListMain线程修改(可能只是重新创建),而另一个线程(在您的情况下是Default)迭代该集合。您可以查看ConcurrentModificationException:

上的文档。

此异常可能由检测到对象的并发修改(当这种修改是不允许的)的方法抛出。

例如,通常不允许一个线程在另一个线程迭代Collection时修改Collection。通常,在这些情况下,迭代的结果是未定义的。

知道Main线程是onCreate方法操作的线程,我认为改变线程调度程序会有所帮助。试着这样修改你的代码:

CoroutineScope(Dispatchers.Main).launch {
...
}

编辑:

函数findSingleCountry可能只在onCreate方法中执行,所以我认为将代码从CoroutineScope中取出实际上会更有帮助.

最新更新