0x1、引言
在开始这篇文章前,我就遇到了第一个关于LiveData的问题:该怎么翻译这个词呢?
- 活的数据?→ 有点奇怪,难不成还有死的数据?
- 可观察数据?→ 感觉跟Observable有点沾边了
- 生命周期感知数据?→ 名字也忒长了...
自己想不到,那就集思广益,尝试向群里的小伙伴发起咨询:
好像也没找到比较好的翻译 (好像越来越可刑),索性就不翻了,哈哈哈~
LiveData 一言以蔽之
LiveData
是 能感知生命周期的
、可观察的
、粘性
的 数据持有者
,以 数据驱动
的方式更新界面。
① 感知谁的生命周期?
具有生命周期感知的组件,一般代指Activity、Fragment,但不局限此,更泛指实现了 Lifecycle.LifecycleOwner 的组件。
如:利用 Lifecycle 让 App进程 拥有生命周期感知 → ProcessLifecycleOwner,具体实现解读:《自定义 LifecycleOwner》
简单点说:实现了Lifecycle那一套的组件,Activity、Fragment默认实现了,所以可以直接用,具体原理解读:《【Jetpack】学穿:Lifecycle → 生命周期 (原理篇)》
② 怎么感知生命周期?
LifecycleOwner
提供了一个getLifecycle()
用于获取Lifecycle实例
;
- 你只需自定义一个 观察者 实现
LifecycleEventObserver
或DefaultLifecycleObserver
,调用Lifecycle实例的addObserve()
添加观察者实例即可。
- 当组件生命周期发生变化,就会通知所有的观察者(回调方法)。
LiveData里,还对观察者包了一层 → LifecycleBoundObserver
图中圈住的①:当组件处于 DESTORYED 状态时,自动移除观察者,这样的好处:避免内存泄露。
图中圈住的②,点开 activeStateChanged()
方法:
当组件处于 STARTED/RESUMED 状态,才发送数据,这样的好处:避免因组件处于非活跃状态,接收LiveData事件导致的崩溃,最常见的就是Activity停止了,还执行相关回调。
③ 可观察
除了 LifecycleBoundObserver 生命周期观察者外,LiveData内部还提供了一个 数据观察者 Observer
可以调用 observe() 添加数据观察者:
在 dispatchingValue()
分发事件,considerNotify()
中回调 onChanged()
,完成数据更新。
④ 粘性
所谓的 粘性,通俗点说:先发送数据,然后订阅,也可以收到之前发的数据。
在LiveData中的表现:新的观察者注册时,会收到注册前分发的值。多说无益,不如来个栗子实在:
// 定义变量 private val nNum = MutableLiveData(0) override fun onCreate(savedInstanceState: Bundle?) { ... // 绑定第一个观察者 nNum.observe(this) { Log.e("Test", "第一个观察者:${nNum.value}") } // 更新值 nNum.setValue(100) // 延迟1000ms后执行 mBinding.btTest.postDelayed({ // 添加新观察者 nNum.observe(this) { Log.e("Test", "第二个观察者:${nNum.value}") } },1000L) }
运行后输出日志如下:
现象:第二个观察者刚注册,就收到分发的值。这是咋回事?
不急不急,先来探一探 值分发的原理,首先,要实现粘性,得把值存起来 吧!跟下构造方法:
不难看出一丝端倪:
- 用一个 Object 类型的 mData 存值;
- 用一个 int 类型的 mVersion 来标识值的版本,初始值-1,如果版本号小于最新版本号,表示当前的值要更新。
跟下更新值的方法:
新值覆盖旧值,使值的版本号自增1,值分发 (遍历所有观察者并分发)
观察者中也持有一个值的版本号,ObserverWrapper
包 Observer 带的私货:
这样设计的好处:数据始终保持最新状态。
值发生变化后遍历所有观察者,看到这里,读者可能有这样的疑问:
生命周期组件处于非活跃状态,如Activity切到后台,此时发生数据变化,然后切回前台,又是怎么更新的?
留意下面的代码:
当生命周期组件发生状态流转,就会回调onStateChanged,Activity从后台到前台自然会走这里,完成数据更新。注意:这里是 单独分发给和生命周期组件绑定的观察者,不是群发!!!
总结下:值变更 + 生命周期组件状态变更 都会引起值分发。
到此,好像也没定位到引起粘性的原因? 嗯,还得再跟一下:LiveData.observe()
→ owner.getLifecycle().addObserver(wrapper)
→ LifecycleRegistry.addObserver()
Lifecycle添加观察者,状态流转,调用 dispatchEvent()
方法完成事件分发: