美文网首页Android开发Android开发经验谈Android技术知识
进阶之路:细究“LiveData ”鲜为人知的身世背景及独特使命

进阶之路:细究“LiveData ”鲜为人知的身世背景及独特使命

作者: 程序老秃子 | 来源:发表于2022-05-18 16:31 被阅读0次

LiveData的由来

LiveData 的由来要追溯到 2017 年,那时,观察者模式有效简化了开发,但诸如 RxJava 一类的库有些太过复杂;为此,架构组件团队打造了 LiveData: 一个专用于 Android 的具备自主生命周期感知能力的可观察的数据存储器类;LiveData 被有意简化设计,这使得开发者很容易上手

LiveData简述

LiveData是一种可观察的数据存储器?

● 存储数据,可以被观察者观察数据的变化

LiveData具有生命周期感知能力?

● 生命周期感知力可以确保只更新处于活跃生命周期的应用组件的观察者?当组件消亡时,不更新?

如果观察者所在的组件的生命周期处于STARTED或者RESUMED状态,则LiveData会认为这个观察者处于活跃状态

LiveData会判断当前观察者注册的这个组件是不是处于活跃状态,处于活跃状态才会回调,否则就不会回调

Event与Stat对应状态图

了解下LiveData

LiveData]是一种可观察的数据存储器类;与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者

如果观察者(由 Observer类表示)的生命周期处于 STARTED 或 RESUMED状态,则 LiveData 会认为该观察者处于活跃状态;LiveData 只会将更新通知给活跃的观察者;为观察 LiveData] 对象而注册的非活跃观察者不会收到更改通知

您可以注册与实现 LifecycleOwner接口的对象配对的观察者;有了这种关系,当相应的 Lifecycle对象的状态变为 DESTROYED时,便可移除此观察者;这对于 Activity 和 Fragment 特别有用,因为它们可以放心地观察 LiveData 对象,而不必担心泄露(当 Activity 和 Fragment 的生命周期被销毁时,系统会立即退订它们)

LiveData的概念

LiveData是Jetpack组件的一部分,更多的时候是搭配ViewModel来使用,相对于Observable,LiveData的最大优势是其具有生命感知的,换句话说,LiveData可以保证只有在组件( Activity、Fragment、Service)处于活动生命周期状态的时候才会更新数据

[图片上传失败...(image-4c404-1652862604497)]

确保UI符合数据状态

LiveData设置的时候遵循的观察者模式,当宿主的生命状态发生改变,LiveData会像里面注册的观察者发出通知,这时候我们可以再观察者的onChange里面更改ui,保持数据

LiveData在注册的时候 会绑定生命周期 ,当宿主销毁的时候 LiveData反注册

当宿主的生命周期变得非活跃状态的时候,那么它将在再次变成活跃状态时能够接受到最新的数据,比如Activity前台到后台 后台到前台

不需要手动处理生命周期

始终保持最新数据

时间总线LiveDataBus

LiveData特性

LiveData 是一种可观察的数据存储器类。并且具有生命周期感知能力,能遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期

● 只有当它关联的应用组件处于生命周期活跃状态时,才会通知对应观察者

● 当关联的应用组件的状态变为 DESTROYED 时,便可移除此观察者,避免内存泄露

● LiveData 仅在数据发生更改时才发送更新,并且仅发送给活跃观察者。此行为的一种例外情况是,观察者从非活跃状态更改为活跃状态时也会收到更新;此外,如果观察者第二次从非活跃状态更改为活跃状态,则只有在自上次变为活跃状态以来,值发生了更改时,它才会收到更新

LivaData优势

确保界面符合数据状态

● LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面;这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新

● 只有组件的生命周期处于活跃状态的时候,才会去更新UI

不会发生内存泄漏

● 观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。

● 当我们的Activity已经结束的时候,这个时候观察者就不会被回调,就不会造成内存泄漏

不会因 Activity 停止而导致崩溃

● 如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件

不再需要手动处理生命周期

● 界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化

数据始终保持最新状态

● 如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据

适当的配置更改

● 如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据

共享资源

● 您可以使用单例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们。LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象

LiveData生命周期

LiveData能够感知页面的生命周期

● 它可以检测页面当前的状态是否为激活状态,或者页面是否被销毁。只有在页面处于激活状态(Lifecycle.State.ON_STARTED或Lifecycle.State.ON_RESUME)时,页面才会收到来自LiveData的通知

● 如果页面被销毁(Lifecycle.State.ON_DESTROY),那么LiveData会自动清除与页面的关联,从而避免了可能引发的内存泄漏问题

● LiveData还提供了一个observeForever()方法,使用起来与observe()没有太大差别,它们的区别主要在于,当LiveData包装的数据发生变化时,无论页面处于什么状态,observeForever()都能收到通知

● 所以,在使用完之后,一定要记得调用removeObserver()方法来停止对LiveData的观察,否则LiveData会一直处于激活状态,你的Activity永远不会被系统自动回收

LiveData的简单使用

[LiveData.java] observe()

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n765" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">@MainThread
 public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
 assertMainThread("observe");
 if (owner.getLifecycle().getCurrentState() == DESTROYED) {
 // ignore
 return;
 }
 LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
 ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
 if (existing != null && !existing.isAttachedTo(owner)) {
 throw new IllegalArgumentException("Cannot add the same observer"
 + " with different lifecycles");
 }
 if (existing != null) {
 return;
 }
 owner.getLifecycle().addObserver(wrapper);
 }</pre>

这个方法主要做了几件事

● 判断是否在主线程添加观察者,如果不在主线程则抛出异常

● 根据LifecycleOwner,和实现的观察者observer,创建一个LifecycleBoundObserver实例 对象,这是一个wrapper类,主要包装LifecycleOwner和observer

● 将observer添加到map中,observer为key,value为wrapper

● 通过LifecycleOwner获取LifecyclerRegistry并注册观察者wrapper

● 还有一个observeForever,表示观察者一直观察,shouldActive()方法直接返回的true,而不是根据应用组件的生命周期是否是STARTED或RESUMED状态

小结

● 通过向LiveData 添加观察者observer,监听数据。注册Observer需要传递,LifecycleOwner对象,实现该对象的接口含有自己的生命周期

● 注册Observer 将LifecycleOwner和Observer包装到一个wrapper类中,该类是一个LifecycleObserver的实现类,通过LifecycleOwner获取LifecycleRegistry,并注册生命周期观察者LifecycleObserver

● 当应用组件的生命周期发生变化的时候,通知到这个wrapper类,这样LiveData就感知了应用组件的生命周期了,如果是状态是活动状态,有新的数据则通知观察者。如果生命周期状态为销毁状态DESTROYED,则从Observers Map中移除observer

● 更新数据通过postValue(T value)和setValue(T value),postValue是通过handler切换到主线程,执行setValue,setValue方法则根据应用组件的生命周期是否处于活动状态,如果是活动状态这通知观察者有数据更新

尾述

LiveData简单往往意味着不够强大,而Flow强大又常常意味着复杂,两者往往不能兼得,软件开发过程中常常面临这种取舍

LiveData的简单并不是它的缺点,而是它的特点

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉

PS:有问题欢迎指正,可以在评论区留下你的建议和感受; 欢迎大家点赞评论,觉得内容可以的话,可以转发分享一下

相关文章

网友评论

    本文标题:进阶之路:细究“LiveData ”鲜为人知的身世背景及独特使命

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