android notifyDataSetInvalidated

Jetpack架构组件库LiveData工作原理只一篇你就懂

作者: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?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?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?mObserver;
????boolean?mActive;
????//ObserverWrapper在每次注册的时候都会重新new,所以mLastVersion每次都是-1开始。
????int?mLastVersion?=?START_VERSION;//这里就等于-1

????ObserverWrapper(Observer?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面试、数据结构、算法等全套视频资料。

原文链接:,转发请注明来源!