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() } }) } }