Kotlin .add переопределяет все элементы списка в MutableList - PullRequest
0 голосов
/ 02 сентября 2018

У меня есть объект, который содержит изменяемый список

object TrackingEventsList {
    var EventDate: String = ""
    var EventDescription: String = ""
}

object Waybill {
    var WaybillNumber: String = ""
    var OriginHub: String = ""
    var TrackingEvents: MutableList<TrackingEventsList> = ArrayList()
}

Когда я пытаюсь добавить Waybill.TrackingEvents, все предыдущие экземпляры перезаписываются и дублируют последнее добавленное TrackingEvent.

private fun fillTracking(events: NodeList) {
    var list = TrackingEventsList
    for (x: Int in 0 until events.length) {
        var tName = (events.item(x) as Element).tagName
        var event = (events.item(x).firstChild as Text).wholeText
        if (tName == "EventDate") {
            list.EventDate = event
        }
        if (tName == "EventDescription") {
            list.EventDescription = event
        }
    }
    Waybill.TrackingEvents.plus(list)
}

Результат после вызова fillTracking 3 раза:

Waybill.TrackingEvents[0].EventDescription = "Event3"
Waybill.TrackingEvents[1].EventDescription = "Event3"
Waybill.TrackingEvents[2].EventDescription = "Event3"

Ответы [ 2 ]

0 голосов
/ 02 сентября 2018

Поскольку TrackingEventsList - это объект, это означает, что он является единичным (или имеет только один экземпляр). Когда вы проходите цикл, вы всегда обновляете один и тот же экземпляр вашего TrackingEventsList объекта.

Измените TrackingEventsList на это:

data class TrackingEventsList(var eventDate: String, var eventDescription: String)

Создайте новый экземпляр каждый раз, когда вы проходите цикл, а затем добавьте его в список в конце:

private fun fillTracking(events: NodeList) {
    var eventDate: String = ""
    var eventDescription: String = ""
    for (x: Int in 0 until events.length) {
        val tName = (events.item(x) as Element).tagName
        val event = (events.item(x).firstChild as Text).wholeText
        if (tName == "EventDate") {
            eventDate = event
        }
        if (tName == "EventDescription") {
            eventDescription = event
        }
    }
    Waybill.TrackingEvents.plus(TrackingEventsList(eventDate, eventDescription))
}
0 голосов
/ 02 сентября 2018

object в Kotlin - одноэлементный, что означает, что вы не можете его инициализировать, и он имеет только один экземпляр в глобальном масштабе. Поэтому, когда вы изменяете элементы одного экземпляра, вы переопределяете предыдущие данные.

Вы должны изменить их обоих (или, по крайней мере, TrackingEventsList) на class. Если переменные Waybill чувствительны к экземпляру, то это тоже должен быть класс. Но в коде, который вы добавили, я не смог найти ничего, что говорило бы, что вы используете его как синглтон, поэтому я оставил его как единое целое.

class TrackingEventsList (
        var eventDate: String = "",
        var eventDescription: String = "")

/**
 * Also want to point out that this is still a singleton. If the data inside is instance-specific, you need to change it 
 * to a class. 
 */
object Waybill {
    var waybillNumber: String = ""
    var originHum: String = ""
    var trackingEvents: MutableList<TrackingEventsList> = ArrayList()
}

private fun fillTracking(events: NodeList) {
    val item = TrackingEventsList()
    for (x: Int in 0 until events.length) {
        var tName = (events.item(x) as Element).tagName
        var event = (events.item(x).firstChild as Text).wholeText

        if (tName == "EventDate") {
            item.eventDate = event
        }
        if (tName == "EventDescription") {
            item.eventDescription = event
        }
    }

    Waybill.trackingEvents.add(item)
}

И вы должны изучить соглашения об именах для Kotlin; поля никогда не начинаются с заглавной буквы, если это не статическая константа (в этом случае она полностью верхняя)

...