This is the 19th day of my participation in the More text Challenge. For details, see more text Challenge
Follow my official account “Ananzhuo” to learn more
StateFlow and Livedata
Both similarities and differences between
There are a lot of similarities between StateFlow and Livedata if you look closely. Both are designed to look at data and are ideal for responsive development.
But there are some differences:
- The StateFlow construct has a default value, but Livedata does not
- Livedata can receive data updates only when its life cycle is in the started or resumed state, while StateFlow can receive data even when it is back to the background.
Cold flow of heat flow
Cold flow: The producer starts emitting data when the consumer calls the collect method. The following code example is a cold flow.
(2.. 9).asFlow().collect{ println(it) }Copy the code
Heat flow: StateFlow is heat flow in this article, and the producer will transmit data without calling the collect method.
Livedata use
Check out my last post about Livedata
Juejin. Cn/post / 697568…
Juejin. Cn/post / 697831…
StateFlow use
Implement data listening using StateFlow
StateFlow can change the data state with setValue
Here’s a brief introduction to usage:
- Add the Activity and Lifecycle extension libraries
implementation 'androidx. Activity: activity - KTX: 1.2.2'
implementation "Androidx. Lifecycle: lifecycle - livedata - KTX: 2.2.0." "
Copy the code
- Add StateFlow code to the ViewModel
Private val mutableStateFlow = mutableStateFlow (" safe "); StateFlow<String> = mutableStateFlow <String> = mutableStateFlow Fun changeData(data: String) {mutableStateFlow.value = data// Send data}Copy the code
- Data monitoring in the activity
When we click the button, we call the viewModel’s changeData method to update the flow’s data.
BtnSendData. SetOnClickListener {viewModel. ChangeData (" public no. : In peace in zhuo ")} lifecycleScope. Launch {/ / here is run in the main thread, so the following code can update the UI viewModel. StateFlow. Collect {tvShowData. Text = it}}Copy the code
- Implementation effect
This example achieves the following effect: The first time you enter the page StateFlow sends the default value: “Safe “, click the button and call the changeData method of ViewModel to update the data, and display it in TextView.
The usage here is basically the same as that of Livedata, but in the next example you’ll find that StateFlow has much less template code and is much cleaner
Implement the effects of MediatorLiveData using StateFlow
You can check out my post about MediatorLiveData:
Juejin. Cn/post / 697568…
How can the same effect be achieved with StateFlow?
Code for StateFlow implementation:
- Code declaration in ViewModel
class StateFlowMediatorViewModel : ViewModel() {private var count1 = 0 private var count2 = 0 private val flow1 = 0 MutableStateFlow(0) private val flow2 = MutableStateFlow(0) val flow = flow1.combine(flow2) { data1, Data2 -> data1 + data2 } fun Flow1pp () {flow1.value = ++count1// Add 1 to the number of clicks on the first button} fun Flow2pp () {flow2.value = ++count2// Add 1 to the number of clicks on the second button} }Copy the code
- Code declaration in the activity
findViewById<Button>(R.id.btn_mediator1).setOnClickListener { model.flow1pp() } findViewById<Button>(R.id.btn_mediator2).setOnClickListener { model.flow2pp() } lifecycleScope.launch { model.flow.collect { textView? .text = if (it > 10) "$it" else "$it"}}Copy the code
- Implementation effect
The demo in the previous Livadata article was implemented with a very small amount of code, so StateFlow is really good, and it’s definitely better than that
Some features of StateFlow
2021-07-03 New content in this section (follow public account: Ananzhuo learn more knowledge)
Multiple StateFlows are registered simultaneously in the ViewModel
Conclusion: If multiple StateFlows are registered in the ViewModel, only the first registered StateFlow can receive a callback for data updates
Here’s the code to verify:
The activity of the code
LifecycleScope. Launch {multipleViewModel. State11. Collect {logEE (it) count++ TV. The text = "received StateFlow1 data update $count time}" MultipleViewModel. State22. Collect {logEE (it) count++ TV. The text = "received $count StateFlow2 data update time"}} The findViewById < Button > (R.i db tn_state1_senddata) setOnClickListener {multipleViewModel. SendData1 () / / click on the Button to update the first StateFlow value } findViewById<Button>(R.id.btn_state2_senddata).setOnClickListener { MultipleViewModel. SendData2 () / / click on the button to update the second StateFlow value}Copy the code
ViewModel:
Private val state1 = MutableStateFlow<String>(" hahaha 1") private Val State2 = MutableStateFlow<String>(" hahaha 2") private var count = 0 val state11 = state1.asStateFlow() val state22 = state2.asStateFlow() fun sendData1() { count++ state1.value = "state1 changed $count"} fun sendData2() {count++ state2. Value = "state2 changed $count"}Copy the code
2. Achieve results
Through our implementation, we found that:
The first registered State1 calls back a collect on each click to update the TextView display value
The second registered state2 although we also called set state2. Value =”??” “, but never a pullback
This proves the conclusion we stated at the beginning of this section
StateFlow and Livedata are similar and different
2021-07-03 New content in this section (follow public account: Ananzhuo learn more knowledge)
StateFlow receives only one callback for multiple updates to the same data, while Livedata receives multiple callbacks
For example, if we set a button that resets the value of Livedata or StateFlow every time we click it (the value does not change, such as setting Value =4), StateFlow will receive only one callback, but Livedata will receive an unlimited callback. The following two sections demonstrate this with code and effects, respectively
This is not a good or bad feature for StateFlow or Livedata, but a good or bad one
StateFlow sets the same value to value multiple times
- code
Registration code in activity:
LifecycleScope. Launch {multipleViewModel. State11. Collect {logEE (it) count++ TV. The text = "received $count data update time"} multipleViewModel.state22.collect { logEE(it) } }Copy the code
Modify value code in StateFlow:
Fun sendData1() {state1.value = "state1 changed "// We set this value}Copy the code
- Running effect diagram
We found that StateFlow’s Collect only called back the data once, even though we clicked send multiple times
Livedata sets the same value to value multiple times
- code
Code in an Activity
Btn_updatewith_simdata. SetOnClickListener {model. The setData () / / click on the button to send data} model. Livedata. Observe (this) {logEE (the "receiving data is: ${it}") count++ tv_beupdate.text=" ${it}" ${it}") count++ tv_beupdate.text=" ${it}"Copy the code
Code in ViewModel:
val livedata = MutableLiveData<Int>()
fun setData(){
livedata.value=124
}
Copy the code
- The effect
We found that we had sent the same data multiple times, and each time Livedata received a callback to update the data
Follow my official account “Ananzhuo” to learn more