LiveData 是 Android 中一个很有用的项目,它是一种可观察(Observe)的资料存储器类(data holder)。它会感知 Android 的生命周期,也就是说当 Activity 或是 Fragment 在 STARTED
或 RESUMED
时,所被观察的资料才会是在启动状态(active state)的。
在 MVVM 架构中,我们将架构分成 Model - ViewModel - View,而 LiveData 就是负责在 ViewModel 与 View 中的资料传递。而 LiveData 存放的则是 UI 介面上所需要的资料,所以它对於资料的更新需要具有敏感度,当 LiveData 内的资料更新时,View 层应该就要能够立刻更新,减少手动呼叫。
View 层透过观察 ViewModel 层暴露出的 LiveData,当资料变更的时候,就会自动通知 View 层更新画面。
先定义 ViewModel 层,这一层主要是要决定哪些资料要暴露给 View 层,以及要这些资料要从哪边取得,所以 ViewModel 是介於 View 与 Model 的。
class MyViewModel : ViewModel() {
private var _data = MutableLiveData<List<Driver>>()
val data: LiveData<List<Driver>> = _data
...
init{
val result = ...
_data.value = result
}
}
class MyFragment: Fragment(){
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.data.observe(viewLifecycleOwner, {
setText(it)
})
}
...
}
这边我们就完成了一个简单的 LiveData 。回到我们的主题 Flow,我们有没有可能使用 Flow 来替代 LiveData 呢?
首先,我们先来分析一下 LiveData。 LiveData 可以让 View 层「观察」,等到资料更新时,就会把更新的资料通知给 View 层,所以在 View 层就不需要主动去查询现在的值是什麽,只需要静静的等待即可。Observe and forget。
我们复习一下两种 Flow 的用法,Shared Flow 可以与多个订阅者分享资料,当有新的订阅者加入时,会把最後面的几笔资料传给新订阅者。之後每次有新的资料的时候,就会同时发送给所有订阅者。而 State Flow 则是 Shared Flow 的特例,它每次建立的时候一定会有值,而在每次有新订阅者加入时,只会把最後一笔的资料发送给新订阅者,因为 StateFlow 只会储存一个值。
这边我们选择 StateFlow 来作为 LiveData 的替代品。
将上面的 ViewModel 改用 StateFlow 替代
class MyViewModel : ViewModel() {
private var _data = MutableStateFlow<List<Driver>>(emptyList())
val data = _data.asStateFlow()
...
init{
val result = ...
_data.value = result
}
}
class MyFragment: Fragment(){
private var updatesJob: Job? = null
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
updatesJob = lifecycleScope.launch {
viewModel._data.collect {
setText()
}
}
}
...
override fun onDestroy() {
super.onDestroy()
updatesJob?.cancel()
}
}
可以发现,我们除了将 LiveData 用 Flow 取代之外,我们在 View 层还必须要使用 lifecycleScope.launch
来把 StateFlow 包装起来,因为 collect
是一个 suspend 函式。
为了避免在离开的时候还继续收资料,必须要在离开画面的时候把 Job 给停掉。
不过在 lifecycle:lifecycle-runtime-ktx:2.4.0
会改,但是目前还是只有 alpha 版而已。
Flow 能够替代 LiveData 是肯定的,不过因为 LiveData 非常简单使用,所以以目前来说不一定需要使用 Flow 来替代 LiveData 。毕竟 LiveData 与 Activity/Fragment 的生命周期绑在一起,当画面结束的时候,订阅的资料也就不会继续更新。如果以目前的 Flow 来说,首先要思考的是我们在 View 层就需要建立一个 Scope 让这个 Flow 跑在背景,等到结束画面的时候,还要记得把它停掉。这样子很容易就出错了。
或许我们可以等到更稳定的时候,Flow 像现在的 LiveData 那麽实用的时候才来改。
Migrating from LiveData to Kotlin’s Flow
A safer way to collect flows from Android UIs
<<: Day16:今天来聊一下如何使用njRAT RAT Trojan控制Windows电脑攻防
>>: Day30. Blue Prism本届最终章 –BP幕後花絮
前言 今天将针对activity的跳转来复习复习 正文 这次采用bundle来传值,并区分start...
字体样式 今天来介绍几个设计字体样式的标签 有了昨天使用标签的概念 今天就可以直接把这些效果套用在句...
这个章节的重点在於资讯管理系统的实体环境的保护。 不是这种保护 XD 不过,比较常跟受稽方讨论到乖乖...
好的,你很辛苦的写了很多API function,但是你却不希望闲杂人等没事就call一下你的API...
来到了中秋连假的第一天,买不到云上的月亮,我们就到云上买台机器来玩玩吧 1. 使用EC2好处? EC...