Home > database >  Is it possible to pass a widget as a parameter to a function in Kotlin
Is it possible to pass a widget as a parameter to a function in Kotlin

Time:11-25

There are several switches in the app's layout, and when these switches are pressed, the value of sharedPreference is changed to determine whether a specific function is performed. For example, if the funcOnOff switch is off, the voice notification function is off, and when fromOnOff is off, caller information cannot be checked when a notification is received.

I am using several source codes that work almost similarly as below. Is it possible to pass multiple android.widgets as parameters to a function so that these actions can be acted upon as a single function?

var funcOnOff: Switch = findViewById(R.id.func_on_off)
var fromOnOff: Switch = findViewById(R.id.from_on_off)
var timeOnOff: Switch = findViewById(R.id.time_on_off)
var contentOnOff: Switch = findViewById(R.id.content_on_off)

funcOnOff.setOnCheckedChangeListener { buttonView, isChecked ->
        if (isChecked) {
            editor.putString("func", "ON")
        } else {
            editor.putString("func", "OFF")
        }
        editor.commit()
    }
    fromOnOff.setOnCheckedChangeListener { buttonView, isChecked ->
        if (isChecked) {
            editor.putString("from", "ON")
        } else {
            editor.putString("from", "OFF")
        }
        editor.commit()
    }
    timeOnOff.setOnCheckedChangeListener { buttonView, isChecked ->
        if (isChecked) {
            editor.putString("time", "ON")
        } else {
            editor.putString("time", "OFF")
        }
        editor.commit()
    }

CodePudding user response:

If I understand correctly, you can make a factory method for the OnCheckedChangeListeners.

fun onCheckedChangedListenerForPreferenceKey(key: String): CompoundButton.OnCheckedChangeListener = { _, isChecked ->
    if (isChecked) {
        editor.putString(key, "ON") // wouldn't using putBoolean be better?
    } else {
        editor.putString(key, "OFF")
    }
    editor.commit()
}

Then you can do:

funcOnOff.setOnCheckedChangeListener(onCheckedChangedListenerForPreferenceKey("func"))
fromOnOff.setOnCheckedChangeListener(onCheckedChangedListenerForPreferenceKey("from"))
timeOnOff.setOnCheckedChangeListener(onCheckedChangedListenerForPreferenceKey("time"))

Or you can make a list of pairs of switches to preference keys, and iterate through them:

listOf(
    funcOnOff to "func"
    fromOnOff to "from"
    timeOnOff to "time"
).forEach { (switch, key) -> 
    switch.setOnCheckedChangeListener(onCheckedChangedListenerForPreferenceKey(key))
}

CodePudding user response:

As a general alternative to Sweeper's answer - most widget listeners (and a lot of other UI callbacks in Android) pass in the object that generated the event as a parameter. So you can create a function that checks that parameter, and acts accordingly:

// If the signature here matches the listener function, you can pass a reference
// to this function directly
fun handleSwitch(switch: CompoundButton, isChecked: Boolean) {
    when(switch) {
        funcOnOff -> "func"
        fromOnOff -> "from"
        timeOnOff -> "time"
        else -> null
    }?.let { key ->
         editor.putString(key, if (isChecked) "ON" else "OFF").commit()
    }
}

Then you can just apply that to all your switches:

val switches = listOf(funcOnOff, fromOnOff, timeOnOff)
switches.forEach { it.setonOnCheckedChangedListener(::handleSwitch) }

// or if you don't want to use a function reference
switches.forEach {
    it.setOnCheckedChangedListener { switch, enabled -> handleSwitch(switch, enabled) }
}

// or since you're iterating over the switches anyway, you could make the current one
// part of the callback lambda and ignore the parameters
switches.forEach { switch ->
    it.setOnCheckedChangedListener { _, _ -> handleSwitch(switch, switch.isChecked) }
}

You get the idea! Personally I feel like passing a function reference is neater, instead of creating a separate lambda for each switch, but honestly it depends - no need to overcomplicate things if a neat one-liner setup will get the job done!

Also personally I'd probably use a Map instead of the when, like in Sweeper's answer - that way you can define the switches in use and their keys in one place, and then you can assign your listeners by iterating over the map's keys. No repeating yourself by listing the keys in one place, and then again in the when, y'know? Easier to maintain too, you might forget to update one of those places - but this is just a general example!

  • Related