首页 > 解决方案 > 在 Kotlin 中迭代 MutableList 时出现 java.util.ConcurrentModificationException

问题描述

我有一个应用程序,它遍历位置列表并确定用户是否在每个位置周围的范围内。当我使用 SharedPreferences 来存储数据时,我没有遇到这个问题,但是现在我已经切换到 SQLite 数据库,我已经进入java.util.ConcurrentModificationException了以下循环。堆栈跟踪指向循环的第一行。

loop@ for (i in locationList) {
                val distance = getLocationFromReminder(locationList[iterator], currentLocation).toDouble()

                // If the user distance is within the radius distance...
                if (distance <= locationList[iterator].radius) {
                    when (locationList[iterator].inside) {
                        null -> { // WHEN DISTANCE <= RADIUS AND LOCATION IS SET TO NEITHER INSIDE NOR OUTSIDE
                            locationList[iterator].inside = true // Set inside to true
                            locationList[iterator].entered = getTransitionTime() // Set entered to the entrance time
                            addToTransitionArray(iterator, locationList[iterator].entered, true) // Add entrance time to entrance time array
                            // db.addLocationTransition(locationList[iterator], getTransitionTime())

                            sendNotification(this@MapsActivity, "Fence created around current location.", reminder.latLng)
                            val logMessage = "[${getDate()}] Fence created around current location (${locationList[iterator].message}) at ${getTimeStamp()}."
                            logMessage(logMessage)
                            refreshLocationList()
                        }
                        false -> { // ...and reminder.inside == false...
                            locationList[iterator].inside = true
                            locationList[iterator].entered = getTransitionTime()
                            addToTransitionArray(iterator, locationList[iterator].entered, true)

                            // db.addLocationTransition(locationList[iterator], getTransitionTime())
                            locationList[iterator].entranceNoteArray.add(locationList[iterator].entranceNoteArray.size, "-")


                            val logMessage = "[${getDate()}] Entered ${locationList[iterator].message} at ${getTimeStamp()}"
                            logMessage(logMessage)

                            // Send notification
                            sendNotification(this@MapsActivity, "Now entering ${locationList[iterator].message}!", locationList[iterator].latLng)
                            sendSnackbar("Transition logged at ${locationList[iterator].entered}.")
                            refreshLocationList()
                        }
                    } // Otherwise, if the user's distance from the Reminder is farther than its radius...
                } else if (distance > locationList[iterator].radius) {
                    when (locationList[iterator].inside) {
                        null -> { locationList[iterator].inside = false }
                        true -> { // ...and reminder.inside == true...
                            // Notify user that they are exiting perimeter
                            sendNotification(this@MapsActivity, "Now exiting ${locationList[iterator].message}!", reminder.latLng)
                            locationList[iterator].exitNoteArray.add(locationList[iterator].exitNoteArray.size, "-")

                            // Get transition time for most recent exited
                            locationList[iterator].exited = getTransitionTime()
                            locationList[iterator].inside = false
                            addToTransitionArray(iterator, getTransitionTime(), false)
                            addToTimeInsideArray(iterator, getTimeInside(locationList[iterator]))

                            val logMessage = "[${getDate()}] Exited ${locationList[iterator].message} at ${getTimeStamp()}"
                            logMessage(logMessage)
                            sendSnackbar("Transition logged at ${getTimeStamp()}.")
                            refreshLocationList()

                        }
                    }
                }
                iterator++
                continue@loop
            }

对于某些上下文,这是填充 locationList MutableList 的 Reminder 类:

class Reminder : Serializable {
    @SerializedName("address") var address: String = ""
    @SerializedName("city") var city: String = ""
    @SerializedName("state") var state: String = ""
    @SerializedName("zip") var zip: String = ""
    @SerializedName("latLng") var latLng: LatLng = LatLng(0.0, 0.0)
    @SerializedName("radius") var radius: Double = 0.0
    @SerializedName("message") var message: String = ""
    @SerializedName("inside") var inside: Boolean? = null
    @SerializedName("tableList") var tableList: MutableList<String> = mutableListOf("")
    @SerializedName("tableName") var tableName: String = "LOCATIONS${message}"
    @SerializedName("entered") var entered: String = "00:00"
    @SerializedName("exited") var exited: String = "00:00"
    @SerializedName("timeinside") var timeInside: String = ""
    @SerializedName("allentrances") var allEntrances: MutableList<String> = mutableListOf("")
    @SerializedName("allexits") var allExits: MutableList<String> = mutableListOf("")
    @SerializedName("timeinsidearray") var timeInsideArray: MutableList<String> = mutableListOf("")
    @SerializedName("entrancenotearray") var entranceNoteArray: MutableList<String> = mutableListOf("")
    @SerializedName("exitnotearray") var exitNoteArray: MutableList<String> = mutableListOf("")
    @SerializedName("id") var id: Int = 0 // NEW
}

我知道我可能不应该使用整数来遍历这个 MutableList,而且我知道这个问题是由这个循环引起的,

我知道有类似的问题,但他们都在 Java 的上下文中回答了这个问题,我想知道 Kotlin 是否应该做一些不同的事情,或者,最好的方法是什么。我看到人们在谈论使用迭代器,但我很难弄清楚这个问题的确切原因是什么或如何解决它。

如果 Kotlinlang 网站上有一些我没有找到的文档可以帮助我解决这个问题,我将不胜感激。谢谢。

标签: javaandroidsqlitekotlinandroid-sqlite

解决方案


推荐阅读