Jetpack之LiveData

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

如何使用LiveData?

1、创建LiveData对象,存储某种数据类型,因为LiveData是泛型抽象类,通常是在ViewModel类中完成的

ViewModel类中创建LiveData对象

2、获取ViewModel

获取ViewModel对象

其中创建factory的目的主要是为了获取ViewModel,在viewModelProvider调用get方法时会执行factory.create方法通过class.newInstance获取到ViewModel对象

3、观察 LiveData 对象,采用LifecycleOwner来观察生命周期变化

添加观察者

在注册观察者,先判断当前Lifecycle如果处于DESTROYED状态就不添加该观察者。在把传入的LifecycleOwner和Observer包装成LifecycleBoundObserver实例,其中LifecycleBoundObserver继承自ObserverWrapper并实现了GenericLifecycleObserver(继承LifecycleObserver)。最后LifecycleOwner获取Lifecycle对象添加LifecycleBoundObserver生命周期观察者。这就是为什么LiveData对象能够感知生命周期的原因

4、更新LiveData对象

setValue更新LiveData对象

更新LiveData对象的两种方法,一种是主线程setValue,一种是子线程的postValue。跟setValue不同的是,postValue考虑多线程操作,synchronized(mDataLock)后通过主线程handler发送一个runnable,重置标记mPendingData为NOT_SET后执行setValue操作。

setValue流程图

重要方法分析:ObserverWrapper.activeStateChanged(newActive)

activeStateChanged方法

触发条件:1)LifecycleBoundObserver的生命周期发生改变时的回调onStateChanged;2)在setValue更新数据时,如果ObserverWrapper.shouldBeActive为false时;3)在LiveData.observeForever或者activeStateChanged时

1)判断新老状态是否一致,一致直接返回;2)新状态赋值给老状态,判断当前是否有活跃的观察者,如果没有并且现在处于活跃状态则回调onActive;3)活跃观察者数量 += newActive ? 1 : -1;4)活跃观察者数量等于0并且当前状态不活跃就回调onInactive;5)如果当前时活跃状态,则dispatchingValue数据

onActive方法:如果活跃观察者数量从0到1的时回调

onInactive方法:如果活跃观察者数量从1到0时回调

在子类MediatorLiveData中的使用,在onActive时注册所有LiveData源的观察者,在onInactive移除所有LiveData源的观察者;

LiveData的优势?

1、确保界面符合数据状态:LiveData 遵循观察者模式。当生命周期状态发生变化时,或者当数据发生变化时,LiveData 会通知Observer 对象。

2、不会发生内存泄漏:观察者会绑定到Lifecycle上,如果关联的生命周期遭到销毁会自动解除绑定。可以在LifecycleBoundObserver.onStageChanged中知道:

自动解除观察者

3、不会因为Activity停止而发生崩溃:如果观察者处于非活跃状态,就不会再接收到LiveData事件。在发送事件之前先判断下当前observer是否处于活跃状态 (observer.mActive)

4、不再需要手动管理生命周期:界面组件只是观察相关数据,而LiveData自动处理生命周期,因为添加了Lifecycle生命周期观察者,可以感知生命周期变化

5、界面始终保持最新数据:如果界面在非活跃状态切换回活跃状态时,因为发生生命周期变化,会发送一次LivaData事件。试想一下曾经从个人信息页跳转到编辑页后,修改成功后是如何将最新数据更新到个人信息页面的?可能通过eventbus,也可能通过广播,也可能是startActivityForResult等,但是这些操作都要从新去绑定视图数据,相对比下可见LiveData在页面数据传输之间提供了非常精简的操作。

6、适当的配置修改:如果Activity或者Fragment重启了,也会接收到最新到数据,跟5的机制是一样的

7、共享数据:可以创建出单例来提供服务,需要相应资源的观察者只要观察LiveData对象。

创建LiveDataBus,提供LiveData数据管理器

LiveDataBus
使用LiveDataBus

通过LiveDataBus可以很方便的统一管理LiveData数据。但试想一下如果上个页面启动下个页面后发送了一个LiveData事件,在下个页面onCreate时添加对应的LiveData数据的观察者,就会发生先发送LiveData事件后添加观察者还能接收到事件的问题?对于LiveData本身来说根据LifecycleOwner的生命周期变化并且达到可以发送事件的条件,观察者就会接收到一次LiveData事件。那如果就不要这种情况出现,该怎么办呢?通过刚才分析setValue的流程图,我们可以发现在通知观察者数据变化之前需要通过三个条件,那么解决这个问题的办法就应运而生了,假如我们可以打破其中任一个条件,后注册的观察者都不会接收到先发送的LiveData事件。在三个条件中其中有两个是关于生命周期管理的,我们最好不要去破坏生命周期管理,因为可能会发生很多问题,那么我们就打破observer.mLastVersion >= mVersion这个条件就能阻止这个过程的发生。在Java中修改运行时,那么就可以用反射来执行,我们只要得到让observer.mLastVersion==mVersion就ok了。

合并LiveData之MediatorLiveData

MediatorLiveData是LiveData子类,允许合并多个LiveData源。只要任何原始的LiveData源对象发生更改,就可以触发MediatorLiveData变化。例如数据需要从数据库和网络获取,就可以通过MediatorLiveData来观察数据库LiveData和网络获取的LiveData的变化

MediatorLiveData

addSource创建的ObserverWrapper是AlwaysActiveObserver,AlwaysActiveObserver是一直处在活跃状态的(shouldBeActive(){return true}),会接收所有的事件并且不会自动移除,需要手动移除

转换LiveData

在开发过程中,我们可能希望在发送给观察者事件之前处理一下数据,或者变换成另一个LiveData数据源,这很像RxJava。而在LivaData这里,lifecycle软件包下提供Transformations类来实现。

Transformations.map():对存储在 LiveData 对象中的值应用函数,并将结果传播到下游

map()

Transfromations.switchMap(): 对存储在 LiveData 对象中的值应用函数,并将结果解封和分派到下游。传递给 switchMap() 的函数必须返回 LiveData 对象

switchMap

你可能感兴趣的:(Jetpack之LiveData)