Jetpack 之LiveData源码详细分析

简介:LiveData是Jetpack 一系列库之一,它是一个对组件的生命周期具有感知能力且可以被观察的数据存储类,它没有对存储的数据类型做限制,可以存储任何类型的数据。与ViewModel经常搭配使用,观察者需要在主线程与livedata进行绑定,且livedata数据更新通知最终也是发送到主线程交给观察者去操作。

 

LiveData优点:

1.不会发生内存泄漏,当所依赖的组件销毁时会对依赖该组件的观察者进行释放。

2.可以自动感知所依赖组件的生命周期状态,当处于非活跃状态时则不会进行通知更新操作,不需要手动去处理。

3.数据与组件进行分离,降低了耦合度。

4.当组件状态发生改变时可立即更新。

5.当组件从非活跃状态恢复到活跃状态时(活跃状态:onResume,onPause),livedata会将最新的数据通知给观察者。

通过以下源码分析的过程,会对以上优点全部涉及。

此处使用了viewmodel与LiveData结合的代码进行分析,再后续中会对viewmodel进行详细讲解

源码分析:

在项目中对库进行导入,目前所使用的是最新版本的库

livedata:1.1.1
viewmodel:1.1.1

Jetpack 之LiveData源码详细分析_第1张图片

首先我们在ViewModel中实例化了一个LiveData

Jetpack 之LiveData源码详细分析_第2张图片

然后在我们的activity中调用observe,传入的第一个参数为我们LiveData所监听的组件,第二个参数传入的是观察LiveData数据变化的观察者

Jetpack 之LiveData源码详细分析_第3张图片

 

追踪进入observe,在此处会通过LifecycleBoundObserver将我们的传递进来的观察者与组件进行一层封装,然后放到map中进行保存,此时注册流程走完。

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
   //如果不是在主线程调用则抛出异常,这里判断的主要原因是因为Android 中在子线程无法进行涉及UI的操作
 assertMainThread("observe");
//如果当前监听的组件的生命周期走到了destroy,则直接返回,不往下进行
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }
//将observer观察者与owner放入LifecycleBoundObserver进行保存封装并返回一个LifecycleBoundObserver新的实例wrapper 
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//通过map将封装了observer观察者与owner的LifecycleBoundObserver对象进行保存。
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//如果map中此观察者已经被添加过了,但没有与当前组件绑定则抛出异常
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
//如果map中此观察者已经被添加过了,则直接返回
    if (existing != null) {
        return;
    }
//将wrapper作为观察者添加到组件对应的Lifecycle,这样当组件的生命周期发生改变时会通知到wrapper,lifecycle的原理在另一篇文章有写
    owner.getLifecycle().addObserver(wrapper);
}

当我们的wrapper被添加到Lifecycle中后,组件的生命周期发生变化时我们的onStateChanged方法就会被调用,并且如果处于活跃状态时会把我们最新的数据通知给观察者,通过观察发现,如果观察者依赖的组件的生命周期走到了DESTROY,那么会从map中移除该观察者

Jetpack 之LiveData源码详细分析_第4张图片

     public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
//移除观察者
                removeObserver(mObserver);
                return;
            }
//当处于活跃状态时会会将最新的数据通知观察者
            activeStateChanged(shouldBeActive());
        }

此处演示所用的livedata为它的子类MutableLiveData,不影响源码分析和追踪,当我们调用livedata的setValue方法时,会回调到观察者的onChanged方法,也就是说当数据准备好后调用setValue方法就通知到了观察者

Jetpack 之LiveData源码详细分析_第5张图片

Jetpack 之LiveData源码详细分析_第6张图片

Jetpack 之LiveData源码详细分析_第7张图片

进入setValue继续追踪,通过官方注释可以看出,此方法必须在主线程进行调用,如果想要在主线程进行使用则可以通postValue方法,在setvalue方法中,先将mData来对数据进行保存,这里之所以要如此操作的原因是如果当前组件处于非活跃状态,当组件恢复到活跃状态时会从之前的mData中获取先前保存的值发送给依赖它的观察者进行更新,这是实现上面优点第五条所述的原因之一。

 /**
     * Sets the value. If there are active observers, the value will be dispatched to them.
     * 

* This method must be called from the main thread. If you need set a value from a background * thread, you can use {@link #postValue(Object)} * * @param value The new value */ @MainThread protected void setValue(T value) { //对主线程进行判断 assertMainThread("setValue"); mVersion++; //此处对传入的数据进行保存,在后面会用到 mData = value; dispatchingValue(null); }

postvalue其内部就是发送一个runable到主线程执行setvalue方法

    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
//将一个runable发送到主线程去执行,在它的run方法内会执行setvalue方法
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

继续追踪进入dispatchingValue方法,会遍历map,并调用considerNotify方法

   void dispatchingValue(@Nullable ObserverWrapper initiator) {
//如果此方法正在被调用则直接返回
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
//对存放LifecycleBoundObserver(其内部保存了传递进来的观察者以及所监听的组件)的map进行遍历并调用considerNotify方法
                for (Iterator, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
//调用完成后重置标志位
        mDispatchingValue = false;
    }

进入considerNotify方法,会发现在最后调用了观察者的onchanged方法并将setvalue方法中传入的参数传入,所以通过这个流程会发现在最后,观察者observer的onchanged方法被调用,完成了最后的通知。

 

如果当前所监听的组件没有处于活跃状态则会调用activeStateChanged方法对观察者的状态进行设置

   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.
//如果组件没有处于活跃状态,shouldBeActive它是一个抽象方法由子类去实现,其内部会获得当前监听的组件的生命周期状态并判断是否大于onstart,如果没有则返回false
        if (!observer.shouldBeActive()) {
//更改观察者的活跃状态
            observer.activeStateChanged(false);
            return;
        }
//mLastVersion 与mVersion初始化时都是START_VERSION,也就是说相等,在setvalue时mVersion首先会+1
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
//此处调用观察者的onchanged方法并将setvalue方法中传入的参数传入
        observer.mObserver.onChanged((T) mData);
    }
//该方法会在多个地方调用,主要作用是根据状态决定是否触发通知更新操作
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;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
//如果处于活跃状态,触发通知操作,
                dispatchingValue(this);
            }
        }

 

你可能感兴趣的:(Jetpack 之LiveData源码详细分析)