Understanding of a paragraph in the reorganization of Android Compose

Posted by dgray on Sat, 18 Sep 2021 05:20:27 +0200

Do not rely on the side effects of executing composable functions, as reorganization of functions may be skipped. If you do this, users may encounter strange and unpredictable behavior in your application. Side effects are any changes that are visible to the rest of the application. For example, the following operations are all dangerous side effects:

  • Write properties of shared objects
  • to update   ViewModel   Observable items in
  • Update sharing preferences

When I first came into contact with compose, I didn't understand this sentence. Now looking back, I feel I can understand it

Take an official example:

 

//Instantiate SharePreference object
val mainSharePref: SharedPreferences = MyApplication.getInstance().getSharedPreferences("main_share", android.content.Context.MODE_PRIVATE)
val value: Boolean = mainSharePref.getBoolean("isSelected",false)
val editor: SharedPreferences.Editor = mainSharePref.edit()
@Composable
fun SharedPreDemo(){
    Column() {
        SharedPrefsToggle("Check",value){
            editor.putBoolean("isSelected",value)
            editor.commit()
        }
    }
}
@Composable
fun SharedPrefsToggle(
    text: String,
    value: Boolean,
    onValueChanged: (Boolean) -> Unit
) {
    Row {
        Text(text)
        Checkbox(checked = value, onCheckedChange = onValueChanged)
    }
}

The above code creates a composable item to update   SharedPreferences   The value in. The composable item should not be read or written from the shared preference itself.

When you run the above code, you will find a strange and unpredictable behavior (in fact, it doesn't take effect) when you click CheckBox

So how should I write it

Official method: then this code moves the read and write operations to the in the background process   ViewModel. The application logic uses the callback to pass the current value to trigger the update. (half understood)

I changed the code. I think it should look like this

@Composable
fun SharedPrefsToggle1(
    text: String,
    value: MutableState<Boolean>,
) {
    Row {
        Text(text)
        Checkbox(checked = value.value, onCheckedChange = {
            value.value=it
            GlobalScope.launch {
                editor.putBoolean("isSelected",value.value)
                editor.commit()
            }
        })
    }
}

In the onCheckedChange callback method in the checkbox, you can directly use the kotlin coroutine to update. (I don't know what a collaborative process is? Baidu is recommended, which roughly means that the function is similar to that of threads, but lighter than threads)

Now look at this sentence:

Do not rely on the side effects of executing composable functions, as reorganization of functions may be skipped

This side effect should refer to the callback. Like the first example, no matter how you click the checkbox, it has no effect, which is equivalent to skipping the reorganization of the function

Attach the entire demo

//Instantiate SharePreference object
val mainSharePref: SharedPreferences = MyApplication.getInstance().getSharedPreferences("main_share", android.content.Context.MODE_PRIVATE)
val value: Boolean = mainSharePref.getBoolean("isSelected",false)
val editor: SharedPreferences.Editor = mainSharePref.edit()
@Composable
fun SharedPreDemo(){
    Column() {
        SharedPrefsToggle("Check",value){
            editor.putBoolean("isSelected",value)
            editor.commit()
        }

        val value1= remember {
            mutableStateOf(value)
        }
        SharedPrefsToggle1("Check",value1)
    }
}

@Composable
fun SharedPrefsToggle(
    text: String,
    value: Boolean,
    onValueChanged: (Boolean) -> Unit
) {
    Row {
        Text(text)
        Checkbox(checked = value, onCheckedChange = onValueChanged)
    }
}

@Composable
fun SharedPrefsToggle1(
    text: String,
    value: MutableState<Boolean>,
) {
    Row {
        Text(text)
        Checkbox(checked = value.value, onCheckedChange = {
            value.value=it
            GlobalScope.launch {
                editor.putBoolean("isSelected",value.value)
                editor.commit()
            }
        })
    }
}

Topics: Android html