【Jetpack】学穿:LiveData → ???(上)

简介: 在开始这篇文章前,我就遇到了第一个关于LiveData的问题:该怎么翻译这个词呢?

0x1、引言


在开始这篇文章前,我就遇到了第一个关于LiveData的问题:该怎么翻译这个词呢?


  • 活的数据?→ 有点奇怪,难不成还有死的数据?
  • 可观察数据?→ 感觉跟Observable有点沾边了
  • 生命周期感知数据?→ 名字也忒长了...


自己想不到,那就集思广益,尝试向群里的小伙伴发起咨询:


网络异常,图片无法展示
|


好像也没找到比较好的翻译 (好像越来越可刑),索性就不翻了,哈哈哈~


LiveData 一言以蔽之


LiveData能感知生命周期的可观察的粘性数据持有者,以 数据驱动 的方式更新界面。


① 感知谁的生命周期?


具有生命周期感知的组件,一般代指Activity、Fragment,但不局限此,更泛指实现了 Lifecycle.LifecycleOwner 的组件。


如:利用 LifecycleApp进程 拥有生命周期感知 → ProcessLifecycleOwner,具体实现解读:《自定义 LifecycleOwner》


简单点说:实现了Lifecycle那一套的组件,Activity、Fragment默认实现了,所以可以直接用,具体原理解读:《【Jetpack】学穿:Lifecycle → 生命周期 (原理篇)》


② 怎么感知生命周期?


  • LifecycleOwner 提供了一个 getLifecycle() 用于获取 Lifecycle实例


  • 你只需自定义一个 观察者 实现 LifecycleEventObserverDefaultLifecycleObserver,调用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值分发 (遍历所有观察者并分发)


网络异常,图片无法展示
|


网络异常,图片无法展示
|


观察者中也持有一个值的版本号,ObserverWrapperObserver 带的私货:


网络异常,图片无法展示
|


这样设计的好处:数据始终保持最新状态


值发生变化后遍历所有观察者,看到这里,读者可能有这样的疑问:


生命周期组件处于非活跃状态,如Activity切到后台,此时发生数据变化,然后切回前台,又是怎么更新的?


留意下面的代码:


网络异常,图片无法展示
|


当生命周期组件发生状态流转,就会回调onStateChanged,Activity从后台到前台自然会走这里,完成数据更新。注意:这里是 单独分发给和生命周期组件绑定的观察者,不是群发!!!


总结下:值变更 + 生命周期组件状态变更 都会引起值分发。


到此,好像也没定位到引起粘性的原因? 嗯,还得再跟一下:LiveData.observe()owner.getLifecycle().addObserver(wrapper)LifecycleRegistry.addObserver()


网络异常,图片无法展示
|


Lifecycle添加观察者,状态流转,调用 dispatchEvent() 方法完成事件分发:


网络异常,图片无法展示
|


网络异常,图片无法展示
|


相关文章
|
6月前
|
前端开发 Java API
Jetpack MVVM 七宗罪之五: 在 Repository 中使用 LiveData
Jetpack MVVM 七宗罪之五: 在 Repository 中使用 LiveData
116 0
|
6月前
|
前端开发 JavaScript Android开发
Jetpack MVVM 七宗罪之四: 使用 LiveData/StateFlow 发送 Events
Jetpack MVVM 七宗罪之四: 使用 LiveData/StateFlow 发送 Events
148 0
|
4月前
|
XML 存储 API
Jetpack初尝试 NavController,LiveData,DataBing,ViewModel,Paging
Jetpack初尝试 NavController,LiveData,DataBing,ViewModel,Paging
|
Android开发
Android JetPack组件之LiveData的使用详解
Android JetPack组件之LiveData的使用详解
158 0
Android JetPack组件之LiveData的使用详解
|
前端开发 数据处理 调度
Android 基于Jetpack LiveData实现消息总线
在Android开发中,跨页面传递数据(尤其是跨多个页面传递数据)是一个很常见的操作,可以通过Handler、接口回调等方式进行传递,但这几种方式都不太优雅,**消息总线**传递数据的方式相比更优雅。
329 0
|
存储 Android开发 数据格式
Android Jetpack系列之LiveData
**LiveData是一种可观察的数据存储类**。LiveData 具有生命周期感知能力,遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的Observer,非活跃状态下的Observer不会受到通知。
141 0
|
Android开发
安卓Jetpack狠活——Lifecycles与LiveData(二)
书接上回,我们看过了LiveData的使用,自然也就明白了这玩意虽然好,但不能处处到位,因为需要你自己去post后才能得到,那如何不用在子线程一直苦苦等待就能给人一种在实时更新的感觉呢?那自然要用到我们的狠活——Lifecycle。
135 0
|
Android开发
安卓Jetpack狠活——Lifecycles与LiveData(一)
今天在工作时,测试突然提了一个Bug给我,要求我将APP中某活动页面的UI界面要根据用户在由此页面跳转的下个页面操作,在返回时要实时更新。
115 0
|
存储 自然语言处理 前端开发
Jetpack 系列(2)—— 为什么 LiveData 会重放数据,怎么解决?
Jetpack 系列(2)—— 为什么 LiveData 会重放数据,怎么解决?
1219 0
Jetpack 系列(2)—— 为什么 LiveData 会重放数据,怎么解决?