美文网首页Android技术知识@IT·互联网
LiveData 与 StateFlow,我该用哪个?

LiveData 与 StateFlow,我该用哪个?

作者: 搬砖小老弟 | 来源:发表于2022-06-09 14:53 被阅读0次

    前言

    LiveData 相信大家都非常熟悉了,但是由于协程与 Flow 的不断发展,之前所使用的技术也正在不断被替代,而 LiveData 的功能与 StateFlow 很相似,所以,很多人都在考虑使用 StateFlow 去替代 LiveData。

    这里,我们就分析下,LiveData 与 StateFlow 的优缺点,以及我们该如何抉择。

    LiveData 与 StateFlow 的区别

    关于 LiveData 与 StateFlow,网上说的最多的区别,其实就是「官方指导文档」中所讲解的这两点,这里我直接搬运过来:

    • StateFlow 需要将初始状态传递给构造函数,而 LiveData 不需要。
    • 当 View 进入 STOPPED 状态时,LiveData.observe() 会自动取消注册使用方,而从 StateFlow 或任何其他数据流收集数据的操作并不会自动停止。如需实现相同的行为,您需要从 Lifecycle.repeatOnLifecycle 块收集数据流。

    关于第一点,对于 LiveData 与 StateFlow 的使用并不能起决定性的作用,因为在创建 StateFlow 的时候,你可以传入 null 进去,就像这样:

    val stateFlow = MutableStateFlow<String?>(null)
    

    而在第二点中,LiveData 会跟生命周期绑定,能够自动取消注册,这个看起来是优点,但是,其实也是一个缺点。

    为什么这样说?

    因为对于数据而言,它其实并不需要关心调用者的生命周期,它只需要负责数据读取与存储即可,所以,为什么要考虑数据使用者的状态?这时,可能有的人会说,“数据基本上都是与视图进行绑定,所以,视图消失的时候,数据自然也用不上了,所以自动取消很好啊”,确实,这样的确很好,但是有时在数据读取的之后,我们并非希望它每次都是在刷新视图,而是进行存储、写日志、上报等他用,而这时,自动取消就会变成了一种负担。

    因此,数据与取消绑定应该剥离开来,可以用统一的方式获取数据,在数据进行调用前,再依据情况判断是否与生命周期进行关联。这个判断并非为代码判断,而是开发者的逻辑判断,因为只有开发者清楚,这些代码是否需要与生命周期相关联,若要关联,可以使用 lifecycleScope 或 ViewModelScope 进行解决,这里就以 lifecycleScope 为主进行说明。

    解决有两种方式:

    • lifecycleScope.launch
    • repeatOnLifecycle

    lifecycleScope.launch

    launch 里面的代码由 lifecycleScope 进行控制,若对象生命周期结束了,则 launch 里面的代码也会被取消。

    repeatOnLifecycle

    这个主要用于当对象运行到生命周期的某个阶段的时候,就自动触发相应的功能:

    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            GlobalScope.launch {
                repeatOnLifecycle(Lifecycle.State.RESUMED){
                    println("repeatOnLifecycle RESUMED 已被执行")
                }
            }
        }
    
        override fun onResume() {
            super.onResume()
            println("onResume 已被执行")
        }
    }
    

    日志输出:

    I/System.out: onResume 已被执行
    I/System.out: repeatOnLifecycle RESUMED 已被执行
    

    当然,也可以使用以下方法来实现:

        lifecycleScope.launchWhenCreated {  }
        lifecycleScope.launchWhenStarted {  }
        lifecycleScope.launchWhenResumed {  }
    

    被动回调与主动收集

    上面说的只是「官方指导文档」所提及的「LiveData 与 StateFlow 的区别」,但是,我觉得这两种说法,还是不能决定我该用 LiveData 还是 StateFlow,因为关于 LiveData 的生命周期的优势,可以使用 lifecycleScope+StateFlow解决。所以,我从另外一个角度谈谈我是怎么理解与判断的,那就是被动回调与主动收集。

    被动回调

    相信了解过观察者模式的同学都知道,当被观察者有改动的时候,就会通知观察者,但是,其实在这个时候,观察者只知道被观察者有改动了,并不清楚外部的情况,例如生命周期走到哪里了?是什么地方触发了被观察者去更新等等,所以,我认为 LiveData 这种更新数据方式为被动回调。

    主动收集

    对于 StateFlow 而言,并不是每次数据更新都会回调到 collect 中了,而是在 collect 的时候,看看最新数据是哪些,然后进行读取,等 collect 运行完后,即使数据更新了,也不会回调到 collect 中,需要开发者自己再次调用 collect,才能再次获取数据。

    所以,对于 StateFlow,其实更像一个单独的数据管理,核心并不在于观察者模式,更强调于用户主动去获取数据,所以,我认为这种方式为主动收集。

    总结

    由于被动回调与主动收集的区别,这时我们就很清晰什么时候该用哪种方式了。

    假如数据与视图进行强绑定,或者说,一旦数据改变了,需要更改多处地方 UI,那么,这时使用 LiveData 更合适,但是,假如你只想对数据进行管理,清楚每次数据刷新的时机,那么使用 StateFlow 更合适。

    相关文章

      网友评论

        本文标题:LiveData 与 StateFlow,我该用哪个?

        本文链接:https://www.haomeiwen.com/subject/nudmmrtx.html