将 arraylist.map() 与 kotlin 协程一起使用时出现 ArrayIndexOutOfBoundsException

ArrayIndexOutOfBoundsException when use arraylist.map() with kotlin coroutines

这是我获取资产项的函数

fun getAccessoriesFromAssets() {
    view.onAccessoriesLoaded(false)
    launch(Dispatchers.IO) {
        val tempCategoryList: ArrayList<String> =
            (view as BodyFaceEditorActivity).assets.list("accessories")?.toCollection(ArrayList()) ?: arrayListOf()
        tempCategoryList.map { categoryPath ->
            accessoryCategoriesFromAssets.add(AccessoryCategory(categoryPath, categoryPath))
            async(Dispatchers.IO) {
                val tempItemList: ArrayList<String> =
                    view.assets.list("accessories/$categoryPath")?.toCollection(ArrayList())
                        ?: arrayListOf()
                tempItemList.map { itemPath ->
                    accessoryItemsFromAssets.add(
                        AccessoryItem(categoryPath, itemPath, false)
                    )
                }
            }
        }.awaitAll()
        launch(Dispatchers.Main) { view.onAccessoriesLoaded(true) }
    }
}

有时会发生 ArrayIndexOutOfBoundException(运行 100 次,发生 1 次),所以我认为协程有问题。但这是什么?

Logcat说错误在这一行

accessoryItemsFromAssets.add(
   AccessoryItem(categoryPath, itemPath, false)
)

这是我的资产文件夹结构

/accessories
  |
  |____/pack1
  |      |
  |      |_item1.png
  |      |_item2.png
  |      |_...
  |____/pack2
         |
         |_item1.png
         |_item2.png
         |_...

感谢您的帮助!

如果你用 async 启动一堆协程,那么所有这些协程将同时 运行。在 Java 中,集合默认不是线程安全的。因此,如果您让所有这些协同程序更新同一个集合,它将随机失败。您应该通过使用 Colletions.synchronizedCollection().

包装它(在创建时)来使 accessoryItemsFromAssets 线程安全