LiveData使⽤与源码分析——完全搞懂LiveData原理
⼀、LiveData简介
LiveData是google官⽅架构JetPack系列的⼀个响应式开发框架,LiveData是⼀个可以被观察的数据持有者类。说到响应式开发或者说观察者就不免想到RxJava,RxJava将观察者模式运⽤的炉⽕纯青。但LiveData和RxJava的定位是不⼀样的,LiveData主要⽤于搭建MVVM架构,并在其中作为数据持有者,LiveData能监听组件的⽣命周期变化,这样⼀来只会更新处于活跃状态的组件。
LiveData的特点:
1)采⽤观察者模式,数据发⽣改变,可以⾃动回调(⽐如更新UI)。
2)不需要⼿动处理⽣命周期,不会因为Activity的销毁重建⽽丢失数据。
3)不会出现内存泄漏。
4)不需要⼿动取消订阅,Activity在⾮活跃状态下(pause、stop、destroy之后)不会收到数据更新信息。
LiveData 的⽣命周期感知是由Lifecycle来实现的,不了解Lifecycle的可以查看
⼆、使⽤⽅法
在分析源码前,简单的介绍⼀下LiveData的使⽤,根据使⽤来逐⼀对源码进⾏分析
可以在viewmodel 中这样使⽤:
// Declaring it
val liveDataA = MutableLiveData<String>()
// Trigger the value change
liveDataA.value = someValue
可以在fragment 中这样使⽤:
class MutableLiveDataFragment :Fragment(){
// 当liveDataA 的数据发⽣变化,就会调⽤Observer 的onChanged()函数
private val changeObserver = Observer<String>{ value ->
value?.let { = it }
}
override fun onAttach(context: Context?){
getLiveDataA().observe(this, changeObserver)
}
}
使⽤⾮常简单,⽅便,完全不⽤考虑更新数据的时候UI的状态
三、源码分析
由于 LiveData 是⼀个 abstract class,我们不能直接⽣成他的实例。官⽅有提供他的实现类MutableLiveData:
public class MutableLiveData<T>extends LiveData<T>{
@Override
public void postValue(T value){
// LiveData.postValue() 是⼀个 protected ⽅法
super.postValue(value);
}
@Override
public void setValue(T value){
// LiveData.setValue() 是⼀个 protected ⽅法
super.setValue(value);
}
}
创建了Livedata 后,需要通过observe⽅法或者observeForever ⽅法设置⼀个回调,这个回调接⼝就是Observer
回调接⼝
public interface Observer<T>{
/**
* Called when the data is changed.
* @param t The new data
*/
void onChanged(@Nullable T t);
}
// 注意,他是 abstract class
public abstract class LiveData<T>{
...省略其他代码...
// 只有 onStart 后,对数据的修改才会触发 Changed()
public void observe(@NonNull LifecycleOwner owner,@NonNull Observer<T> observer){}
// ⽆论何时,只要数据发⽣改变,就会触发 Changed()
public void observeForever(@NonNull Observer<T> observer){}
...省略其他代码...
}
observeForever 的实现跟 observe 是类似的,这⾥我们重点看⼀下 observe()的实现过程:
@MainThread
public void observe(@NonNull LifecycleOwner owner,@NonNull Observer<?super T> observer){
assertMainThread("observe");
/
/如当前UI的状态的是DESTROYED,就不绑定这个回调了
Lifecycle().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;
}
//把wrapper 与Activity/Fragment的⽣命周期,建⽴关系,
//当UI的⽣命周期发⽣变化的时候,就会去回调wrapper中的 onStateChanged
}
3.1、⽣命周期发⽣变化,LiveData回调接⼝的调⽤情况
接下来,我们来看⼀个当⽣命周期发⽣变化的时候,LifecycleBoundObserver 都做了那些操作,熟悉LifeCycle的⼩伙伴,应该会很熟悉,⽣命周期发⽣变化时,会调⽤onStateChanged
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<?super T> observer){
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive(){
Lifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
// 当⽣命周期发⽣变化时,会调⽤这个函数
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event){
// 当UI的⽣命周期为DESTROYED,取消对数据变化的监听,移除回调函数
Lifecycle().getCurrentState()== DESTROYED){
removeObserver(mObserver);
return;
}
//改变数据,传递的参数是shouldBeActive(),它会计算看当前的状态是否是STARTED,也就是 onStart-onPause 期间⽣命周期activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner){
return mOwner == owner;
}
@Override
void detachObserver(){
}
}
我们继续看下activeStateChanged⽅法是如何对数据进⾏处理的,它是ObserverWrapper 类中的⼀个⽅法,
private abstract class ObserverWrapper {
final Observer<?super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<?super T> observer){
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner){
return false;
}
void detachObserver(){
}
void activeStateChanged(boolean newActive){
// 当前的⽣命周期和上⼀次的⽣命周期状态,是否发⽣变化,没有发⽣变化,就直接返回。
/
/ onStart-onPause 为 true 在这之外的⽣命周期为false
if(newActive == mActive){
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
notify for mi band// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount ==0;
LiveData.this.mActiveCount += mActive ?1:-1;
if(wasInactive && mActive){
// 这是⼀个空函数,可在代码中根据需要进⾏重写
onActive();
}
if(LiveData.this.mActiveCount ==0&&!mActive){
// 这是⼀个空函数,可在代码中根据需要进⾏重写
onInactive();
}
//结合上⾯的状态判断,我们知道了,⽣命周期状态从Inactive 到 Active,就会调⽤回调函数
if(mActive){
dispatchingValue(this);
}
}
}
为什么在⽣命周期的活跃状态 从Inactive 到 Active,要去调⽤livedata设置的回调函数呢?
原因是,在Inactive (在⾮ onStart-onPause 周期内 )状态,数据发⽣了变化,然后在回到Active(onStart-onPause 周期内),如果不去调⽤回调函数,会出现UI的界⾯,还在显⽰上⼀次的数据,所以需要调⽤回调函数。
再回到代码流程,到了调⽤dispatchingValue(this);这个函数在数据发⽣变化,也是会去调⽤的,所以在后⾯分析,先来看下,数据发⽣变化,代码的流程
3.2、LiveData数据发⽣发⽣变化,调⽤回调接⼝
当数据发⽣变化,需要调⽤LiveData的setValue,postValue ⽅法
从setValue⼊⼿,看⼀下流程
protected void setValue(T value){
assertMainThread("setValue");
/
/mVersion 表⽰数据发⽣了变化
mVersion++;
// 保存了这次变化的数据
mData = value;
//分发数据变化,调⽤回调函数
dispatchingValue(null);
}
进⼊到dispatchingValue⽅法
该⽅法中,是通过⼀个while 循环来通知回调函数,
1. 如果调⽤dispatchingValue⽅法,传⼊参数,则调⽤指定的ivedata的回调函数
2. 如果调⽤dispatchingValue⽅法,传⼊null,则在for循环中,依次通知所有livedata的回调函数
void dispatchingValue(@Nullable ObserverWrapper initiator){
if(mDispatchingValue){
mDispatchInvalidated =true;
return;
}
//进⼊while 循环前,设置为true,如果此时另外⼀个数据发⽣变化,到了此函数中就直接在上⾯返回了
mDispatchingValue =true;
do{
//开始for循环前,设置为false,for循环完,也会退出while循环
mDispatchInvalidated =false;
if(initiator != null){
considerNotify(initiator);
initiator = null;
}else{
for(Iterator<Map.Entry<Observer<?super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext();){
().getValue());
//这⾥mDispatchInvalidated 为true,表⽰在while循环未结束的时候,有其他数据发⽣变化,并调⽤了该函数
//在上⾯的if判断中设置了 mDispatchInvalidated = true,
// 结束本次for循环,没有退出while循环,开始下⼀次for循环
if(mDispatchInvalidated){
break;
}
}
}
}while(mDispatchInvalidated);
//退出while 后,设置为false,正常处理数据变化
mDispatchingValue =false;
}
这⾥有两个变量
mDispatchingValue 这个变量⽤来控制,是否进⼊while 循环,以及while 循环 是否已经结束
mDispatchInvalidated 这个变量⽤来控制for 循环是否要重新开始
看下considerNotify 的函数,调⽤了之前livedata设置的observer的onChanged函数
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论