作者:heiyulong
授权原文:https://mp.weixin.qq.com/s/vZsqMG7yna_EIfh75bgz5A
前言
本次主要讲解的内容:
1、LiveData 核心方法
2、LiveData 原理解析
3、LiveData粘性事件产生的原因
一、LiveData 核心方法:
1、LiveData 公开(public)方法
T?getValue()
//返回当前值。请注意,在后台线程上调用此方法不能保证将接收到最新的值集。boolean?hasActiveObservers()
//如果此LiveData具有活动的观察者,则返回true。boolean?hasObservers()
//如果此LiveData具有观察者,则返回true。void?observe(LifecycleOwner?owner,?Observer?observer)
//(注册和宿主生命周期关联的观察者)将给定的观察者添加到给定所有者的生存期内的观察者列表中。 void?observeForever(Observer?observer)
//(注册观察者,不会反注册,需自行维护)将给定的观察者添加到观察者列表中。 void?removeObserver(Observer?observer)
//从观察者列表中删除给定的观察者。 void?removeObservers(LifecycleOwner?owner)
//删除所有与给定绑定的观察者LifecycleOwner。2、LiveData 受保护(protected)方法
void?onActive()
//(当且仅当有一个活跃的观察者时会触发)当活动观察者的数量从0变为1时调用。void?onInactive()
//(不存在活跃的观察者时会触发)当活动观察者的数量从1变为0时调用。
//这并不意味着没有观察者,可能仍然有观察者,但是它们的生命周期状态不是STARTED或RESUMED (如后退堆栈中的“Avtivity”)。
//您可以通过来检查是否有观察者hasObservers()。void?postValue(T?value)
//(和setValue一样。不受线程环境限制,)将任务发布到主线程以设置给定值。void?setValue(T?value)
//(发送数据,没有活跃的观察者时不分发。只能在主线程。)设置值。二、LiveData 原理解析:
1、observe订阅源码分析
LiveData 注册观察者触发消息分发流程原理分析
首先看看observe方法源码
observe 注册时,可以主动跟宿主生命周期绑定,不用反注册:
@MainThread
public?void?observe(@NonNull?LifecycleOwner?owner,?@NonNull?Observer?super?T>?observer)?{
????//1.?断言,这个方法只能在主线程调用(如果不在主线程注册会抛IllegalStateException异常)
????assertMainThread("observe");
????//2.当前绑定的组件(activity或者fragment)状态为DESTROYED的时候,?则会忽视当前的订阅请求
????if?(owner.getLifecycle().getCurrentState()?==?DESTROYED)?{
????????//?ignore
????????return;
????}
????//3.创建生命周期感知的观察者包装类(把注册进来的observer包装成?一个具有生命周边边界的观察者)
????LifecycleBoundObserver?wrapper?=?new?LifecycleBoundObserver(owner,?observer);
????//4.接着会判断该观察是否已经注册过了,如果是则抛异常,所以要注意,不允许重复注册
????ObserverWrapper?existing?=?mObservers.putIfAbsent(observer,?wrapper);
????//5.对应观察者只能与一个owner绑定
????if?(existing?!=?null?&&?!existing.isAttachedTo(owner))?{
????????throw?new?IllegalArgumentException("Cannot?add?the?same?observer"
????????????????+?"?with?different?lifecycles");
????}
????if?(existing?!=?null)?{
????????return;
????}
????//6.利用Lifecycle,把观察者注册到LifecycleBoundObserver进去,就能监听到宿主生命周期状态的变化
????owner.getLifecycle().addObserver(wrapper);
}总结:
- 1、observe只能在主线程调用,如果不在主线程注册会抛IllegalStateException异常
- 2、当前绑定的组件(activity或者fragment)状态为DESTROYED的时候, 则会忽视当前的订阅请求
- 3、内部会创建生命周期感知的观察者包装类LifecycleBoundObserver(把注册进来的observer包装成 一个具有生命周边边界的观察者)
- 4、对应观察者只能与一个owner绑定,不允许重复注册
- 5、最后利用Lifecycle,把观察者注册到LifecycleBoundObserver进去,就能监听到宿主生命周期状态的变化
LifecycleBoundObserver到底承载了哪些信息,接着看...
、LifecycleBoundObserver源码:
从上面的分析可以看出:
利用Lifecycle,把观察者注册到LifecycleBoundObserver进去,这样监听到宿主生命周期状态的变化
一旦一个新的观察者被添加,Lifecycle也会同步它的状态和宿主一致,此时会触发观察者的onStateChanged方法
- 内部会创建生命周期感知的观察者包装类LifecycleBoundObserver(把注册进来的observer包装成 一个具有生命周边边界的观察者)
- 它能监听宿主被销毁的事件,从而主动的把自己反注册,避免内存泄漏
- 此时观察者是否处于活跃状态就等于宿主是否可见, 监听宿主的生命周期,并且宿主不可见时不分发任何数据
LifecycleBoundObserver源码:
//1、LifecycleBoundObserver是LiveData内部类
class?LifecycleBoundObserver?extends?ObserverWrapper?implements?LifecycleEventObserver?{
????@NonNull
????final?LifecycleOwner?mOwner;
????LifecycleBoundObserver(@NonNull?LifecycleOwner?owner,?Observer?super?T>?observer)?{
????????super(observer);
????????mOwner?=?owner;
????}
????@Override
????boolean?shouldBeActive()?{
????????//2、观察者是否活跃就等于宿主的状态是否大于等于STARTED;
????????//如果页面当前不可见,你发送了一条消息,此时是不会被分发的,可以避免后台任务抢占资源,当页面恢复可见才会分发。
????????return?mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
????}
????@Override
????public?void?onStateChanged(@NonNull?LifecycleOwner?source,
????????????@NonNull?Lifecycle.Event?event)?{
????????//3、如果当接收到?DESTROYED?的事件会自动解除跟?owner?的绑定
????????if?(mOwner.getLifecycle().getCurrentState()?==?DESTROYED)?{
????????????removeObserver(mObserver);
????????????return;
????????}
????????//否则说明宿主的状态发生了变化,此时会判断宿主是否处于活跃状态
????????activeStateChanged(shouldBeActive());
????}
????@Override
????boolean?isAttachedTo(LifecycleOwner?owner)?{
????????return?mOwner?==?owner;
????}
????@Override
????void?detachObserver()?{
????????mOwner.getLifecycle().removeObserver(this);
????}
}
//接口,触发观察者的onStateChanged方法
//通过Lifecycle,addObserver(Observer?oberver)
//handleLifecycleEvent(Event?event)
//宿主(Activity?或?Fragment)每次生命周期变化都会回调onStateChange方法
public?interface?LifecycleEventObserver?extends?LifecycleObserver?{
????/**
?????*?Called?when?a?state?transition?event?happens.
?????*
?????*?@param?source?The?source?of?the?event
?????*?@param?event?The?event
?????*/
????void?onStateChanged(@NonNull?LifecycleOwner?source,?@NonNull?Lifecycle.Event?event);
}ObserverWrapper 状态变更后,如果观察者处于活跃状态会触发数据的分发流程
//抽象类
private?abstract?class?ObserverWrapper?{
????final?Observer?super?T>?mObserver;
????boolean?mActive;
????//ObserverWrapper在每次注册的时候都会重新new,所以mLastVersion每次都是-1开始。
????int?mLastVersion?=?START_VERSION;//这里就等于-1
????ObserverWrapper(Observer?super?T>?observer)?{
????????mObserver?=?observer;
????}
????abstract?boolean?shouldBeActive();
????boolean?isAttachedTo(LifecycleOwner?owner)?{
????????return?false;
????}
????void?detachObserver()?{
????}
????void?activeStateChanged(boolean?newActive)?{
????????if?(newActive?==?mActive)?{
????????????return;
????????}
????????//?immediately?set?active?state,?so?we'd?never?dispatch?anything?to?inactive
????????//?owner
????????//更改观察者的状态
????????mActive?=?newActive;
????????boolean?wasInactive?=?LiveData.this.mActiveCount?==?0;
????????LiveData.this.mActiveCount?+=?mActive???1?:?-1;
????????//1、如果此时有且只有一个活跃的观察者则触发onActive
????????if?(wasInactive?&&?mActive)?{
????????????onActive();
????????}
????????//2、没有任何一个活跃的观察者则触发onInactive
????????if?(LiveData.this.mActiveCount?==?0?&&?!mActive)?{
????????????onInactive();
????????}
????????//3、如果此时观察者处于活跃状态,下面就开始分发数据了
????????if?(mActive)?{
????????????dispatchingValue(this);
????????}
????}
}dispatchingValue(this)数据分发流程控制:(内部执行considerNotify(initiator)方法)
void?dispatchingValue(@Nullable?ObserverWrapper?initiator)?{
????if?(mDispatchingValue)?{
????????mDispatchInvalidated?=?true;
????????return;
????}
????mDispatchingValue?=?true;
????do?{
????????mDispatchInvalidated?=?false;
????????if?(initiator?!=?null)?{
????????????//1、如果传递的观察者不为空,则把数据分发给他自己。这个流程是新注册观察者的时候会被触发
????????????considerNotify(initiator);
????????????initiator?=?null;
????????}?else?{
????????????//2、否则遍历集合中所有已注册的的观察者,逐个调用considerNotify,分发数据
????????????for?(Iterator,?ObserverWrapper>>?iterator?=
????????????????????mObservers.iteratorWithAdditions();?iterator.hasNext();?)?{
????????????????considerNotify(iterator.next().getValue());
????????????????if?(mDispatchInvalidated)?{
????????????????????break;
????????????????}
????????????}
????????}
????}?while?(mDispatchInvalidated);
????mDispatchingValue?=?false;
} considerNotify 数据真正分发的地方:
private?void?considerNotify(ObserverWrapper?observer)?{
????//1、观察者当前状态不活跃就不分发
????if?(!observer.mActive)?{
????????return;
????}
????//?Check?latest?state?b4?dispatch.?Maybe?it?changed?state?but?we?didn't?get?the?event?yet.
????//
????//?we?still?first?check?observer.active?to?keep?it?as?the?entrance?for?events.?So?even?if
????//?the?observer?moved?to?an?active?state,?if?we've?not?received?that?event,?we?better?not
????//?notify?for?a?more?predictable?notification?order.
????//2、观察者所在宿主是否处于活跃状态,否则不分发,并且更改观察者的状态为false
????if?(!observer.shouldBeActive())?{
????????observer.activeStateChanged(false);
????????return;
????}
????//3、此处判断观察者接收消息的次数是否大于等于?发送消息的次数(observer被创建之初verison=-1?)
????if?(observer.mLastVersion?>=?mVersion)?{
????????return;
????}
????//4、计算最新的发送消息的次数
????observer.mLastVersion?=?mVersion;
????//5、这里会执行传入的observer的onChanged方法
????observer.mObserver.onChanged((T)?mData);
}2、setValue发送源码分析
setValue源码分析
@MainThread
????protected?void?setValue(T?value)?{
????????assertMainThread("setValue");
????????//这个mVersion是属于LiveData的,然后只在setValue(postValue最终也会调用setValue)的时候会自增1
????????mVersion++;
????????mData?=?value;
????????dispatchingValue(null);
????}同上observer分析,dispatchingValue(this)数据分发流程控制:(内部执行considerNotify(initiator)方法)
void?dispatchingValue(@Nullable?ObserverWrapper?initiator)?{
????if?(mDispatchingValue)?{
????????mDispatchInvalidated?=?true;
????????return;
????}
????mDispatchingValue?=?true;
????do?{
????????mDispatchInvalidated?=?false;
????????if?(initiator?!=?null)?{
????????????//1、如果传递的观察者不为空,则把数据分发给他自己。这个流程是新注册观察者的时候会被触发
????????????considerNotify(initiator);
????????????initiator?=?null;
????????}?else?{
????????????//2、否则遍历集合中所有已注册的的观察者,逐个调用considerNotify,分发数据
????????????for?(Iterator,?ObserverWrapper>>?iterator?=
????????????????????mObservers.iteratorWithAdditions();?iterator.hasNext();?)?{
????????????????considerNotify(iterator.next().getValue());
????????????????if?(mDispatchInvalidated)?{
????????????????????break;
????????????????}
????????????}
????????}
????}?while?(mDispatchInvalidated);
????mDispatchingValue?=?false;
} 、considerNotify 数据真正分发的地方:
private?void?considerNotify(ObserverWrapper?observer)?{
????//1、观察者当前状态不活跃就不分发
????if?(!observer.mActive)?{
????????return;
????}
????//?Check?latest?state?b4?dispatch.?Maybe?it?changed?state?but?we?didn't?get?the?event?yet.
????//
????//?we?still?first?check?observer.active?to?keep?it?as?the?entrance?for?events.?So?even?if
????//?the?observer?moved?to?an?active?state,?if?we've?not?received?that?event,?we?better?not
????//?notify?for?a?more?predictable?notification?order.
????//2、观察者所在宿主是否处于活跃状态,否则不分发,并且更改观察者的状态为false
????if?(!observer.shouldBeActive())?{
????????observer.activeStateChanged(false);
????????return;
????}
????//3、此处判断观察者接收消息的次数是否大于等于?发送消息的次数(observer被创建之初verison=-1?)
????if?(observer.mLastVersion?>=?mVersion)?{
????????return;
????}
????//4、计算最新的发送消息的次数
????observer.mLastVersion?=?mVersion;
????//5、这里会执行传入的observer的onChanged方法
????observer.mObserver.onChanged((T)?mData);
}- 综上分析:LiveData的粘性事件:这种情况被称为LiveData的粘性事件
- 通过同一个LiveData
- 在更改数据的时候调用setValue(postValue最终也会调用setValue)的时候内部维护的mVersion会自增1,mVersion初始值是-1
- 在监听数据变化的时候,既调用observer监听的时候,每次内部都会在通过包装类中new ObserverWrapper,内部维护了一个mLastVersion变量,mLastVersion也是初始值为-1,所以注意了,每执行一次observer方法内部维护mLastVersion都会新创建而变为-1
- 结论所以只要之前有发射过一次数据,那么后面注册的观察者都会接收到之前发射过的数据
这也是为什么通常使用LiveData时,在大多数情况下,应用组件的 onCreate() 方法是开始观察 LiveData 对象的正确着手点,就是为了避免粘性事件的发生。
后台私信回复 免费领取 SpringCloud、SpringBoot,微信小程序、Java面试、数据结构、算法等全套视频资料。
