从源码看Jetpack(二)LiveData一图流

八股一图流

一图流

在这里插入图片描述

在这里插入图片描述

LivaData通过observe()添加 与LifecycleOwner绑定的观察者;观察者变为活跃时回调最新的数据;使用setValue()、postValue()更新数据时会通知回调所有的观察者。

设置数据

  • postValue():可在子线程调用获取到主线程的Looper通过Handler切换到主线程,执行Runnable对象的run,run中还是调用setValue()

  • setValue():将mVersion自增1代表数据更新,随后调用dispatchingValue()分发,如果ObserverWrapper参数为null就迭代器遍历通知Map中所有Observer;如果参数不为null(粘性事件),就通知传入的Observer。
    遍历的过程中,有一个boolean变量用来判断遍历过程中数据是否发生变化,如果发送变化则重新遍历,最后根据Observer的生命周期状态决定是否回调onChange()方法
    considerNotify通知方法的3次if,前2次是判断状态,第3次是判断mVersion和mLastVersion。

使用setValue()、postValue()更新数据时会通知回调所有的观察者

添加观察者

observe():先判断是否是主线程和LifecycleOwner是否DESTORYED状态

  • 是Destroyed直接return
  • 不是才能添加,用ObserverWrapper包裹LifecycleOwner和Observer通过Lifecycle监听Owner的生命周期变化。将其存储到一个**Map<observer,ObserverWrapper>**中。

生命周期变化

Owner的生命周期状态变化:回调ObserverWrapper内部类的onStateChanged()修改Wrapper的状态,如果Owner变成DESTROYED状态则移除Observer。如果是和**上次不一样的活跃状态**,就调用ObserverWrapper的一个方法,其中还是用dispatchingValue(this@ObserverWrapper)进行分发。

  • ObserverWrapper 不为空,通知这一个ObserverWrapper。
  • ObserverWrapper为空,则遍历通知所有Observer。遍历的过程中,有一个boolean变量用来判断遍历过程中数据是否发生变化,如果变化则重新遍历,最后根据Observer的生命周期状态决定是否回调onChange()方法

分发找到对应的ObserverWrapper用considerNotify具体通知:3次if,前2次判断Owner状态,第3次判断mVersionmLastVersion

只有Observer生命周期活跃,并且ObserverWrapper.mLastVersion < LiveData.mVersion才回调onChanged()

粘性事件

先调用LiveData的postValue/setValue后注册observerobserver依然能收到onChange()。

为什么会触发?

因为LiveData在注册Observer时,会触发LifecycleBoundObserver状态改变,会将ON_CREATE,ON_START,ON_RESUME三种状态分发给Observer,就通知onChange。

mLastVersion初始值-1属于新建的ObservermVersion属于LiveData每次更新数据就加1判断如果mLastVersion < mVersion(更新过数据),就回调onChange()方法通知Observer。)

解决粘性事件

反射干涉Version

每次setValue或postValue,mVersion都+1,要mLastVersion>=mVersion则调用Observer.onChange()。我们在observe()添加观察者之前某处改ObserverWrapper.mLastVersion,令mLastVersion < mVersion

不改LiveData.mVersion是担心LiveData会影响其他的Observer。

通过源码我们通过反射在observer中找到mObservers对象和当前mVersion,然后便可以在这里将mVersion赋值给mLastVersion。

存在延迟,无法用于对实时性有要求场景;

是线程安全的吗?

它的observer,setvalue等都只能在主线程运行间接指明它是线程安全的。

通过给数据的读写操作加锁来保证数据的线程安全。并且当我们多次调用postValue时,可能导致只会收到最后一次的数据更新通知,这样设计的目的是节省性能,因为UI界面的显示一般只关心最新的数据。

postvalue中加了synchronized锁然后调用setvalue,setvalue中会判断是否是主线程,不是的话不执行。

优点

  1. 确保界面符合数据状态:当生命周期状态变化时,LiveData通知Observer,可以在observer中更新界面。观察者可以在生命周期状态更改时刷新界面,而不是在每次数据变化时刷新界面
  2. 不会发生内存泄漏:当生命周期状态变化时,LiveData通知Observer,可以在observer中更新界面。观察者可以在生命周期状态更改时刷新界面,而不是在每次数据变化时刷新界面
  3. 不会因为activity停止而导致内存泄漏:如果LifecycleOwner生命周期处于非活跃状态,则它不会接收任何 LiveData事件。
  4. 不需要手动解除观察:开发者不需要在onPause或onDestroy方法中解除对LiveData的观察,因为LiveData能感知生命周期状态变化,所以会自动管理所有这些操作。
  5. 数据始终保持最新的状态:数据更新时 若LifecycleOwner为非活跃状态,那么会在变为活跃时接收最新数据。例如,曾经在后台的 Activity 会在返回前台后,observer立即接收最新的数据。

先从LiveData.observe()方法看起:

  • 添加观察者事件在主线程分发. 如果LiveData已经有数据,将直接分发给observer。
  • 观察者只在LifecycleOwner活跃时接受事件,如果变为DESTROYED状态,observer自动移除。
  • 当数据在非活跃时更新,observer不会接收到。变为活跃时 将自动接收前面最新的数据。 *
  • LifecycleOwner非DESTROYED状态时,LiveData持有observer和 owner的强引用,DESTROYED状态时自动移除引用。
  • 参数:owner -控制观察者的LifecycleOwner observer -将接收事件的观察者
class Lifecycle{
	...
	//这是干什么的,就是添加被观察者的
	@MainThread
	public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
	    //只能在主线程中进行
	    assertMainThread("observe");
	    //对owner进行判断,如果是destroyed是没有意义的,不用进行
	    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
	        // ignore
	        return;
	    }
	    //创建一个 LifecycleBoundObserver 对象,将其与传入的 Observer 对象一起存储在 mObservers 集合中,
	    //并将它们附加到 LifecycleOwner 的生命周期中
	    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
	    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
	    if (existing != null && !existing.isAttachedTo(owner)) {
	    //走到此步,说明之前 LiveData 内部已经持有了 observer 对象,且该 observer 对象已经绑定了其它的 LifecycleOwner 对象
	        //此时直接抛出异常
	        throw new IllegalArgumentException("Cannot add the same observer"
	                + " with different lifecycles");
	    }
	    if (existing != null) {
	    //observer 之前已经和同个 owner 一起传进来过了,此处直接返回
	    
	        return;
	    }
	    owner.getLifecycle().addObserver(wrapper);
	}
	...
}

LifecycleBoundObserver内部类

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() {//用来判断当前的LifecycleBoundObserver对象是否应该处于活跃的状态
    //通过检查 LifecycleOwner 的生命周期状态是否至少为 STARTED 来判断是否应该处于活动状态。
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {//监听 LifecycleOwner 的生命周期状态变化
        Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
        if (currentState == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        Lifecycle.State prevState = null;
        while (prevState != currentState) {
            prevState = currentState;
            activeStateChanged(shouldBeActive());
            currentState = mOwner.getLifecycle().getCurrentState();
        }
    }

    @Override//判断当前 LifecycleBoundObserver 对象是否已经附加到指定的 LifecycleOwner 上
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override//将从 LifecycleOwner 中删除此 LifecycleEventObserver 对象
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

LifecycleBoundObserver 对象用于将 Observer 对象与LifecycleOwner 对象绑定在一起,并在 LifecycleOwner 的生命周期状态发生变化时相应地更新 Observer 对象的活动状态。

它实现接口LifecycleEventObserver,实现了onStateChanged方法。上一篇Lifecycle中提到onStateChanged是生命周期状态变化的回调。

在LifecycleOwner生命周期状态变化时 判断如果是DESTROYED状态,则移除观察者。LiveData自动移除观察者特点就来源于此。 如果不是DESTROYED状态,将调用父类ObserverWrapper的activeStateChanged()方法处理 这个生命周期状态变化,shouldBeActive()的值作为参数,至少是STARTED状态为true,即活跃状态为true。

ObserverWrapper 内部类

private abstract class ObserverWrapper {
    final Observer<? super T> mObserver;//存储被包装的 Observer 对象
    boolean mActive;//记录被包装的 Observer 对象是否处于活动状态
    int mLastVersion = START_VERSION;//记录 LiveData 中的数据版本号

    ObserverWrapper(Observer<? super T> observer) {
        mObserver = observer;
    }

    abstract boolean shouldBeActive();//判断被包装的 Observer 对象是否应该处于活动状态

    boolean isAttachedTo(LifecycleOwner owner) {
    //判断被包装的 Observer 对象是否已经附加到指定的 LifecycleOwner 上。
        return false;
    }

    void detachObserver() {//用于将被包装的 Observer 对象从与之关联的 LifecycleOwner 中分离
    }

    void activeStateChanged(boolean newActive) {
    //更新被包装的 Observer 对象的活动状态。在这个方法中,它将检查新的活动状态是否与当前活动状态相同
    //如果不同,则更新活动状态,并根据需要调用 dispatchingValue() 方法分发数据
        if (newActive == mActive) {
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner
        mActive = newActive;
        changeActiveCounter(mActive ? 1 : -1);
        if (mActive) {
            dispatchingValue(this);
        }
    }
}

ObserverWrapper 是 LiveData 中的一个辅助类,用于封装 Observer 对象并管理其活动状态。

最后观察者变为活跃,就使用LiveData的dispatchingValue(observerWrapper)进行数据分发

开始数据分发

void dispatchingValue(@Nullable ObserverWrapper initiator) {
//首先判断是否正在处于分发的状态中,如果处于分发的状态中就将mDispatchInvalidated 设置为true,然后跳出
//为什么要将mDispatchInvalidated 设置为true,是为了避免在分发数据的过程中避免死循环
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {//这里就是粘性事件的进入口
            considerNotify(initiator);
            initiator = null;
        } else {
        //迭代器遍历 mObservers 集合中的所有 ObserverWrapper 对象
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    //considerNotify通知 Observer 对象有关数据的更改
                considerNotify(iterator.next().getValue());
                //在遍历 mObservers 集合期间,如果 mDispatchInvalidated 被设置为 true,则跳出循环,
                //否则继续遍历直到所有 ObserverWrapper 对象都被通知。
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

这里设置的很奇妙,使用了两个变量,for example现在正在更新状态1中,此时mDispatchingValue = true,mDispatchInvalidated = false.
如果当前1还没有更新完,但是状态2已经开始了,此时的状态2就被返回了,然后mDispatchInvalidated = true,然后状态1中正在使用迭代器遍历的ObserverWrapper 对象就会被停止更新,直接跳出循环,然后将mDispatchingValue = false表示现在没有进行更新
使用这个两个变量的作用就是防止同时更新两种状态
如果当前正在分发,则分发无效;observerWrapper不为空,就使用considerNotify()通知真正的观察者,observerWrapper为空 则遍历通知所有的观察者。 observerWrapper啥时候为空呢?这里先留个疑问。 继续看considerNotify()方法:

private void considerNotify(ObserverWrapper observer) {
    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.
    if (!observer.shouldBeActive()) {//这个就是看我们的activity是不是start状态
    //若当前observer对应owner非活跃,就会再调用activeStateChanged方法,
    //并传入false,其内部会再次判断
        observer.activeStateChanged(false);
        return;
    }
    //这里的observer.mLastVersion是我们写的观察者中的版本
    //这里的mVersion是我们livedata中的版本,我们每次的setValue一次,mVersion就会+1
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);回调真正的mObserver的onChanged方法
}

在 LiveData 中,观察者的激活状态有两个维度:内部状态(mActive)和外部状态(shouldBeActive())。内部状态表示 Observer 对象是否处于激活状态,而外部状态表示 Observer 对象最近的状态是否应该是激活状态。这两个状态可能会不同步,例如在 LiveData 的激活状态计数器变化过程中,Observer 对象的激活状态可能会发生变化,但是外部状态可能还没有更新。
这个再次进行判断是为了确保 Observer 对象的状态与 LiveData 的状态保持同步,并避免不必要的通知。
到此,回调的逻辑就清楚了!

通过set/postValue方法触发回调

接下来是我们最重要的一个部分,那就是通过setValue或者postValue方法触发我们的回调,这次我们先来看postValue方法

    protected void postValue(T value) {
        boolean postTask;
        //同步方法,进行上锁
        synchronized (mDataLock) { //pendingData,意思就是尚未被发送的数据
            postTask = mPendingData == NOT_SET; //此处判断本次投递是不是挂起的任务,第一次总是true
            mPendingData = value;//设置挂起数据为当前数据
        }
        //将锁释放
        if (!postTask) { //如果不是挂起任务的话,也就是当上次任务还没有投递完成时
            return; //直接返回
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

这里涉及到了mPendingDate这个成员变量,我们会在后面比较setValue方法中再次提到,这里会首先通过线程池的postToMainThread方法投递mPostValueRunnable的任务,这个任务是在LiveData创建的:

    private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {//上锁
                newValue = mPendingData;//将新值设置为mPendingData,这个值在之前的postValue方法中设置
                mPendingData = NOT_SET;//重新将Pending位设置为NOT_SET
            }
            setValue((T) newValue);//调用setValue方法
        }
    };

至于postToMainThread方法,就是将runnable通过Handler机制投递到主线程中执行,然后调用其setValue方法修改Value的值。我们可以设想一下当只有一条线程执行一次postValue的情况,首先会将mDataLock进行上锁,然后通过Handler将任务发送到主线程执行,这个runnable运行时也会上锁,然后将新值取出,将mPendingData转为NOT_SET状态。最后执行setValue方法更改新值。

在多线程的情况下,我们再来分析,当有两条线程同时执行postValue方法时首先先进入的那条线程会将设置postTask 时的代码块先进行上锁,这样第二条线程只能阻塞在代码块之前;然后第一条线程执行完值的设置时将锁给释放,然后第二条线程就进入了值的设置的阶段,这个时候由于锁被第二条线程给持有了,所以第一条线程在执行runnable时就会被阻塞,第二条线程设置完值之后再将锁给释放,这样第一条线程就执行了runnable方法。不过这个时候第一条线程设置的值实际上是第二条线程中传入的值,因为这个mPendingData是volatile状态的:

volatile Object mPendingData = NOT_SET;

总之,postValue方法保证了在多线程的情况下总是只有一个最新的值被执行具体的setValue操作,这样做的好处就是可以提高性能,且不会在主线程的消息队列中堆积过多任务,导致主线程的阻塞。好了看完了postValue方法之后我们再来看setValue方法:

    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

首先这个方法也是一个只能在主线程调用的方法,其次它维护了一个记录值变化的记录值mVersion,也就是说每次成功对LiveData中的数据进行修改后mVersion的值都会发生变化,以此来判断是否需要分发回调事件,最后触发dispatchingValue方法.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值