Kotlin watch array change

Viewed 2016

I'm trying to be notified when an array changes its content. Through this code I'm able to notify the setting of the array, but nothing happens when a new item is inserted.

var array: MutableMap<String, List<String>> = mutableMapOf()
    set(value) {
        field = value
        arrayListener?.notify()
    }

The only thing I came up with is resetting the array to itself everytime I add, delete o edit items, like this:

array = array

I read this question How to watch for array changes? relative to Javascript, but I'd like an easier solution then creating a new object, can anyone suggest it?

2 Answers

Array's API is quite simple: elements can be written there and can be read from an array.

At 99% (a number without justification, read "the vast majority") array's usages people are satisfied with this simple API. It would be a shame if a simple interface with straightforward implementation was mixed with tricky functionality.

Moving to your problem, a possible approach could be create an array's wrapper

class ArrayWrapper<T> (private val array: Array<out T>, 
                       private val onChange: () -> Unit) {
    val size = array.size

    fun get(index: Int): T {
        return array[index]
    }

    fun set(index: Int, value: T) {
        array[index] = value
        onChange()
    }
}

An example of usage:

val ints = ArrayWrapper(arrayOf(1, 2, 3)) {
    println("Array has been changed")
}

You are currently only observing that a new map is assigned to array variable. Your code won't notify you if the map entry is added or removed from the map.

If you want to observe if the array is reassigned you can use an Observable delegate from Kotlin standard lib.

Note: You should rename array variable that it fits a data structure you have used.

Here is an example:

 var map:  MutableMap<String, List<String>> by Delegates.observable(mutableMapOf()) {
    property, oldValue, newValue ->  
    if (oldValue != newValue) //notify that reference has changed
 }

You can read about observable delegate here.

Since you want to observe changes in the map I think you should take a look at this question. It might help. To archive what you want, you'll have to extend map or create a wrapper around it which will notify you when a map entry is added or removed.

Related