LiveData 与 StateFlow,我该用哪个?

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

前言

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 更合适。

猜你喜欢

转载自juejin.im/post/7103428115971440676