Livedata用的爽吗,StateFlow你也应该了解一下

简介: Livedata用的爽吗,StateFlow你也应该了解一下

StateFlow和Livedata



两者异同


如果你仔细去了解的话会发现StateFlow和Livedata有很多相似之处。两者都是用来观察数据的,非常适合用来做响应式开发。

不过两者也有不同之处的:

  • StateFlow构造中有默认值,Livedata没有
  • Livedata只有生命周期处于started或resumed状态的时候才能收到数据更新,而StateFlow即使退到后台也可以收到数据。


冷流热流


冷流:消费者调用收集collect方法的时候生产者才会开始发射数据,如下代码示例就是冷流。

(2..9).asFlow().collect{
            println(it)
        }
复制代码

热流:本文中StateFlow就是热流,即使不调用collect方法生产者也会发射数据。


Livedata使用


关于Livedata可以查看我前些天的文章

juejin.cn/post/697568…

juejin.cn/post/697831…


StateFlow使用


使用StateFlow实现数据监听

StateFlow可以通过setValue来更改数据状态

下面简单介绍一下用法:

  1. 添加activity和lifecycle扩展库
implementation 'androidx.activity:activity-ktx:1.2.2'
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
复制代码


  1. viewmodel中添加StateFlow代码
private val mutableStateFlow = MutableStateFlow("安安安安卓")//构造中需要有初始值
    val stateFlow: StateFlow<String> = mutableStateFlow//这里为什么要赋值给stateFlow呢,因为stateFlow是不能对value进行赋值的,MutableStateFlow是可以的,这样做可以避免用户在activity中有更新数据的行为
    fun changeData(data: String) {
        mutableStateFlow.value = data//发送数据
    }
复制代码


  1. activity中的数据监听处理

当我们点击按钮的时候调用viewModel的changeData方法,更新flow的数据。

btnSendData.setOnClickListener {
            viewModel.changeData("公众号:安安安安卓")
        }
        lifecycleScope.launch {//这里是运行在主线程的,所以下面的代码可以进行更新ui
            viewModel.stateFlow.collect {
                tvShowData.text = it
            }
        }
复制代码


  1. 实现效果

image.png

本例实现了下面的效果,首次进入页面StateFlow发送默认值:"安安安安卓",点击按钮后调用ViewModel的changeData方法更新数据,在TextView中展示。

这里的使用与Livedata基本一致,不过下一个例子你就会发现StateFlow的模板代码更少,更简洁


使用StateFlow实现MediatorLiveData的效果

关于MediatorLiveData你可以看我这篇文章:

juejin.cn/post/697568…

那么同样的效果使用StateFlow改如何实现呢,下面上代码:

上StateFlow实现的代码:

  1. ViewModel中代码声明
class StateFlowMediatorViewModel : ViewModel() {
    private var count1 = 0//第一个按钮点击的次数
    private var count2 = 0//第二个按钮点击的次数
    private val flow1 = MutableStateFlow(0)
    private val flow2 = MutableStateFlow(0)
    val flow = flow1.combine(flow2) { data1, data2 ->
        data1 + data2//将两个flow融合,分别点击的数量相加
    }
    fun flow1pp() {
        flow1.value = ++count1//点击第一个按钮数量加1
    }
    fun flow2pp() {
        flow2.value = ++count2//点击第二个按钮数量加1
    }
}
复制代码


  1. 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 次"
            }
        }
复制代码


  1. 实现效果

image.png

这里只使用了很少量的代码就实现了上一篇Livadata中的demo效果,所以StateFlow真的很好,而且它的好肯定不止这些的,需要进一步挖掘


StateFlow的一些特点


2021-07-03新增本节内容


ViewModel中同时注册多个StateFlow

先说结论:ViewModel中同时注册多个StateFlow只有第一个注册的StateFlow可以收到数据更新的回调

下面用代码进行验证:

activity中代码

lifecycleScope.launch {
            multipleViewModel.state11.collect {
                logEE(it)
                count++
                tv.text="收到StateFlow1数据更新 $count 次"
            }
            multipleViewModel.state22.collect {
                logEE(it)
                count++
                tv.text="收到StateFlow2数据更新 $count 次"
            }
        }
        findViewById<Button>(R.id.btn_state1_senddata).setOnClickListener {
            multipleViewModel.sendData1()//点击按钮更新第一个StateFlow的值
        }
        findViewById<Button>(R.id.btn_state2_senddata).setOnClickListener {
            multipleViewModel.sendData2()//点击按钮更新第二个StateFlow的值
        }
复制代码


ViewModel中代码:

private val state1 = MutableStateFlow<String>("哈哈哈1")
    private val state2 = MutableStateFlow<String>("哈哈哈哈2")
    private var count = 0
    val state11 = state1.asStateFlow()
    val state22 = state2.asStateFlow()
    fun sendData1() {
        count++
        state1.value = "state1被更改 $count"
    }
    fun sendData2() {
        count++
        state2.value = "state2被更改 $count"
    }
复制代码


2.实现效果

image.png

通过我们的实现效果,我们发现:

第一个注册的state1每次点击都会回调一次collect,更新TextView的展示值

第二个注册的state2虽然我们也调用了设置state2.value="??",但是从来不会回调

这证明了我们本节开始声明的结论


StateFlow和Livedata异同

2021-07-03新增本节内容(关注公众号:安安安安卓 学更多知识)


StateFlow多次更新同一个数据只会收到一次回调,Livedata会收到多次

比如我们设置一个按钮每次点击都会重新设置Livedata或StateFlow的value值(值不变,比如设置value=4),StateFlow只会收到一次回调,但是Livedata可以无限收到回调。下面两小节分别用代码和效果证明

这个特点不能说StateFlow和Livedata孰好孰坏,只能说各有优缺

StateFlow多次设置相同的值给value
  1. 代码

activity中注册代码:

lifecycleScope.launch {
            multipleViewModel.state11.collect {
                logEE(it)
                count++
                tv.text="收到数据更新 $count 次"
            }
            multipleViewModel.state22.collect {
                logEE(it)
            }
        }
复制代码

StateFlow中修改值代码:

fun sendData1() {
        state1.value = "state1被更改"//我们设置设置这个值
    }
复制代码
  1. 运行效果图

image.png

我们发现,尽管我们点击了多次发送数据,但是StateFlow的collect只回调了一次数据

Livedata多次设置相同的值给value


  1. 代码

Activity中的代码

btn_updatewith_simdata.setOnClickListener {
            model.setData()//点击按钮发送数据
        }
        model.livedata.observe(this){
            logEE("收到的数据是:${it}")
            count++
            tv_beupdate.text="收到livedata数据更新请求 $count 次"//收到数据更新后更新ui中textview的值
        }
复制代码


ViewModel中的代码:

val livedata = MutableLiveData<Int>()
    fun setData(){
        livedata.value=124
    }
复制代码


  1. 效果

image.png

我们发现,相同的数据我们发送了多次,每次Livedata都收到了数据更新的回调



相关文章
|
6月前
|
安全
一道面试题:介绍一下 LiveData 的 postValue ?
一道面试题:介绍一下 LiveData 的 postValue ?
81 0
|
4月前
LiveData和ViewModel源码学习
LiveData和ViewModel源码学习
|
API Swift iOS开发
|
存储 缓存 前端开发
学会使用LiveData和ViewModel,我相信会让你在写业务时变得轻松🌞
当你学会如何使用LiveData和ViewModel后,你会发现,世界变得简单了... 在2017年,那时,观察者模式有效的简化了开发,但是诸如RxJava一类的库有一些太过复杂,学习成本
|
Android开发 UED 容器
再谈事件分发
再谈事件分发
117 0
|
缓存 前端开发 Java
真香!Kotlin+MVVM+LiveData+协程 打造 Wanandroid!
真香!Kotlin+MVVM+LiveData+协程 打造 Wanandroid!
真香!Kotlin+MVVM+LiveData+协程 打造 Wanandroid!
|
JavaScript
手写代码:实现一个EventBus
EventBus,事件总线。总线一词来自于《计算机组成原理》中的”系统总线“,是指用于连接多个部件的信息传输线,各部件共享的传输介质。我们通常把事件总线也成为自定义事件,一般包含`on`、`once`、`emit`、`off`等方法。在Vue2中想要实现EventBus比较简单,直接暴露出一个`new Vue()`实例即可,以此为思路,我们应该如何自定义实现EventBus呢?
514 0
手写代码:实现一个EventBus
Livedata源码详细解析-面试这么讲就ok
Livedata源码详细解析-面试这么讲就ok
289 0
Livedata源码详细解析-面试这么讲就ok
|
Android开发
android源码宇宙-StateFlow
android源码宇宙-StateFlow
478 0
android源码宇宙-StateFlow
ViewModel源码研究之聊聊onSaveInstanceState和onRetainNonConfigurationInstance的区别
ViewModel源码研究之聊聊onSaveInstanceState和onRetainNonConfigurationInstance的区别
ViewModel源码研究之聊聊onSaveInstanceState和onRetainNonConfigurationInstance的区别