Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I monitor a variable in Kotlin?

Tags:

kotlin

I hope to monitor a variable, I will do sometings when the variable changed, maybe just like Code A.

How can I write these code in Kotlin? Thanks!

Code A

var myList: List<Int>

registerMonitorVar(myList)

fun onVariableChange(){
   if (myList.size>=1){
      btnDelete.enabled=true
   }
}

To ice1000

Thanks! but the following code doesn't work! I don't know how to init allList when I need set property.

private lateinit var allList: MutableList<MSetting> set(value) {
        field = value
        onVariableChange()
}

private  var allList=mutableListOf<MSetting>() set(value) {
        field = value
        onVariableChange()
}

fun onVariableChange(){
    if (allList.size>=1){

     }
}

To humazed:

Thanks! why isn't the following code correct?

 private var allList: MutableList<MSetting>  by Delegates.vetoable(mutableListOf<MSetting>())
    { property, oldValue, newValue ->
        {
            btnRestore.isEnabled=(newValue.size >= 1)
            btnBackup.isEnabled=(newValue.size >= 1)
        }

    }

To humazed and ice1000

Thanks! The system can't monitor the change of the var allList when I use Code 2

 private var allList: MutableList<MSetting>  by Delegates.observable(mutableListOf<MSetting>())
    { property, oldValue, newValue ->
        btnRestore.isEnabled = newValue.size >= 1
    }

Code 1

allList=SettingHandler().getListAllSetting().toMutableList() // Observable Work

Code 2

allList.clear()
 allList.addAll(SettingHandler().getListAllSetting().toMutableList()) //Observable Doesn't Work
like image 377
HelloCW Avatar asked Dec 18 '22 23:12

HelloCW


2 Answers

Kotlin observable and vetoable is perfect for this use case.

vetoable is doing just what you want. from the doc:

vetoable:
Returns a property delegate for a read/write property that calls a specified callback function when changed, allowing the callback to veto the modification.

for your example, you can use:

var myList: List<Int> by Delegates.vetoable(listOf()) { property, oldValue, newValue ->
    if (newValue.size >= 1)
        true // apply the change to myList
    else
        false // ignore the change. ie. myList stay the same.
}

or simply:

var myList: List<Int> by Delegates.vetoable(listOf()) { property, oldValue, newValue ->
    newValue.isNotEmpty()
}

After your edit. I see in your next example observable is more suitable as you seem to want the list to be changed regardless of any condition.

var allList: MutableList<String>  by Delegates.observable(mutableListOf<String>()) { property, oldValue, newValue ->
    btnRestore.isEnabled = newValue.size >= 1
    btnBackup.isEnabled = newValue.size >= 1
}

your code didn't work because you added unnecessary {} and used vetoable without returning neither true nor false.



For the edited answer. it deserves its own question but I'm going to answer it here anyway.

you could use list and when you want to change the list replace it with the new list. this has performance implications since you creating a new list every time you need to add or remove an item.

or you could extend the list class or use extension functions to react to add and delete operations. ex:-

fun main(args: Array<String>) {
    val myList = mutableListOf<Int>()

    myList.addAllAndNotify(listOf(1, 2, 3, 4))
    myList.addAllAndNotify(listOf(1, 2, 88, 9))
}

fun <E> MutableList<E>.addAllAndNotify(elements: Collection<E>) {
    addAll(elements)
    doStuff(this)
}

fun <E> doStuff(list: List<E>) {
    println("list = ${list}")
}

the output:

list = [1, 2, 3, 4]
list = [1, 2, 3, 4, 1, 2, 88, 9]  

finally, you could take a look at this nice lib which has ObservableList if this what you need you better of using it instead of writing it yourself.

like image 168
humazed Avatar answered Jan 04 '23 22:01

humazed


You can override the and setter.

var myList: List<Int> // maybe here's a missing initialization 
  set(value) {
    field = value
    onVariableChange()
  }

fun onVariableChange() {
   if (myList.size >= 1) {
      btnDelete.enabled = true
   }
}

By this, if you do myList = blabla, onVariableChange will be called.

To the edit, why doesn't

private var allList = mutableListOf<String>()
    set(value) {
        field = value
        onVariableChange()
    }


fun onVariableChange() {
    if (allList.size >= 1) {
    }
}

This code work?

To the comment, you may use this:

private var allList = listOf<String>()
    set(value) {
        field = value
        onVariableChange()
    }
like image 21
ice1000 Avatar answered Jan 05 '23 00:01

ice1000