Kotlin .add переопределяет все элементы списка в MutableList
У меня есть объект, который содержит изменяемый список
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 ответа
object
в Kotlin есть singleton, что означает, что вы не можете его инициализировать, и он имеет только один экземпляр в глобальном масштабе. Поэтому, когда вы изменяете элементы одного экземпляра, вы переопределяете предыдущие данные.
Вы должны изменить их обоих (или, по крайней мере, 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; поля никогда не начинаются с заглавной буквы, если только это не статическая константа (в этом случае она полностью верхняя)
Поскольку 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))
}