LiveData 源码分析

栏目: 编程工具 · 发布时间: 6年前

内容简介:LiveData 源码分析

注:本文所有代码基于 android.arch.lifecycle 1.0.0-alpha1

_(:з」∠)_ 流水账一篇

Lifecycle-aware Components 源码分析 一文中,我们已经分析了 Lifecycle 框架中所有的 lifecyle 事件产生流程以及分发流程。本文将会基于这部分知识来分析 Lifecycle 框架中的 LiveData 组件。

提出问题

结合 LiveData javadoc , LiveData 文档,我们可以了解到 LiveData 主要作用是数据发生变化时通知 Observer ,那么 LiveData 是如何实现这部分内容的呢?

LiveData

有监听得先有注册,先来看 observe 方法:

@MainThread
public void observe(LifecycleOwner owner, Observer<T> observer){
   if (owner.getLifecycle().getCurrentState() == DESTROYED) {
       // ignore
       return;
   }
   LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
   LifecycleBoundObserver existing = mObservers.putIfAbsent(observer, wrapper);
   if (existing != null && existing.owner != wrapper.owner) {
       throw new IllegalArgumentException("Cannot add the same observer"
               + " with different lifecycles");
   }
   if (existing != null) {
       return;
   }
   owner.getLifecycle().addObserver(wrapper);
   wrapper.activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
}

observe 方法需运行在主线程中,执行时会将 Observer 传入 LifecycleBoundObserver ,并将 LifecycleBoundObserver 通过 addObserver 注册至 Lifecycle ,紧接着调用了 LifecycleBoundObserveractiveStateChanged 方法。

接着看 LifecycleBoundObserver

class LifecycleBoundObserverimplements LifecycleObserver{
   public final LifecycleOwner owner;
   public final Observer<T> observer;
   public boolean active;
   public int lastVersion = START_VERSION;

   LifecycleBoundObserver(LifecycleOwner owner, Observer<T> observer) {
       this.owner = owner;
       this.observer = observer;
   }

   @SuppressWarnings("unused")
   @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
   void onStateChange(){
       if (owner.getLifecycle().getCurrentState() == DESTROYED) {
           removeObserver(observer);
           return;
       }
       // immediately set active state, so we'd never dispatch anything to inactive
       // owner
       activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));

   }

   void activeStateChanged(booleannewActive){
       if (newActive == active) {
           return;
       }
       active = newActive;
       boolean wasInactive = LiveData.this.mActiveCount == 0;
       LiveData.this.mActiveCount += active ? 1 : -1;
       if (wasInactive && active) {
           onActive();
       }
       if (LiveData.this.mActiveCount == 0 && !active) {
           onInactive();
       }
       if (active) {
           dispatchingValue(this);
       }
   }
}

static boolean isActiveState(State state){
   return state.isAtLeast(STARTED);
}

不难看出 onStateChange 会接收所有的 lifecycle 事件。当 LifecycleOwner 的状态处于 STARTEDRESUMED 时,传入 activeStateChanged 的值为 true,即 LifecycleBoundObserver 会被标记为激活状态,同时会增加 LiveDatamActiveCount 计数。接着可以看到, onActive 会在 mActiveCount 为 1 时触发, onInactive 方法则只会在 mActiveCount 为 0 时触发。这里就与 LiveData javadoc 所描述的完全吻合(In addition, LiveData has onActive() and onInactive() methods to get notified when number of active Observers change between 0 and 1. This allows LiveData to release any heavy resources when it does not have any Observers that are actively observing.)。

此后,如果 LifecycleBoundObserver 处于激活状态,则会调用 dispatchingValue

private void dispatchingValue(@Nullable LifecycleBoundObserver initiator){
   if (mDispatchingValue) {
       mDispatchInvalidated = true;
       return;
   }
   mDispatchingValue = true;
   do {
       mDispatchInvalidated = false;
       if (initiator != null) {
           considerNotify(initiator);
           initiator = null;
       } else {
           for (Iterator<Map.Entry<Observer<T>, LifecycleBoundObserver>> iterator =
                   mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
               considerNotify(iterator.next().getValue());
               if (mDispatchInvalidated) {
                   break;
               }
           }
       }
   } while (mDispatchInvalidated);
   mDispatchingValue = false;
}

其中 mDispatchingValue , mDispatchInvalidated 只在 dispatchingValue 方法中使用,显然这两个变量是为了防止重复分发相同的内容。接下来,无论哪个路径都会调用 considerNotify

private void considerNotify(LifecycleBoundObserver observer){
   if (!observer.active) {
       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 (!isActiveState(observer.owner.getLifecycle().getCurrentState())) {
       return;
   }
   if (observer.lastVersion >= mVersion) {
       // 数据已经是最新
       return;
   }
   observer.lastVersion = mVersion;
   //noinspection unchecked
   observer.observer.onChanged((T) mData);
}

注: mVersion 代表的是数据变化的次数,下文会补充说明。

显然 considerNotify 的作用就是通知处于激活状态且数据未更新的 Observer 数据已发生变化。

其中 mData 即是 LiveData 当前的数据,默认是一个全局 Object:

private static final Object NOT_SET = new Object();
private Object mData = NOT_SET;

可能会有人担心当 LiveDatamData 未发生变更时,第一次调用 observe 会将 NOT_SET 传递到 Observer 中。事实上并不会,因为 LiveDatamVersionLifecycleBoundObserverlastVersion 的默认值均为 START_VERSION

public abstract class LiveData<T>{
    ...
    static final int START_VERSION = -1;
    private int mVersion = START_VERSION;
    ...
    class LifecycleBoundObserverimplements LifecycleObserver{
        ...
        public int lastVersion = START_VERSION;
        ...
    }
    ...
}

observer.lastVersion >= mVersion 判断时就会直接返回而不执行 observer.observer.onChanged((T) mData)

再来看 setValue

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

setValueobserve 方法一样均需要在主线程上执行,当 setValue 的时候 mVersion 的值会自增,并通知 Observer 数据发生变化。

setValue 还有另一个替代的方法 postValue

protected void postValue(T value){
   boolean postTask;
   synchronized (mDataLock) {
       postTask = mPendingData == NOT_SET;
       mPendingData = value;
   }
   if (!postTask) {
       return;
   }
   AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

private final Runnable mPostValueRunnable = new Runnable() {
   @Override
   public void run(){
       Object newValue;
       synchronized (mDataLock) {
           newValue = mPendingData;
           mPendingData = NOT_SET;
       }
       //noinspection unchecked
       setValue((T) newValue);
   }
};

其中 AppToolkitTaskExecutor 是通过一个以 Main Looper 作为 Looper 的 Handler 将 mPostValueRunnable 运行在主线程上,所以 postValue 可以运行在任意线程上,而 ObserverOnChange 回调会执行在主线程上。

最后再看下 observeForever

@MainThread
public void observeForever(Observer<T> observer){
   observe(ALWAYS_ON, observer);
}

private static final LifecycleOwner ALWAYS_ON = new LifecycleOwner() {

   private LifecycleRegistry mRegistry = init();

   privateLifecycleRegistryinit(){
       LifecycleRegistry registry = new LifecycleRegistry(this);
       registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
       registry.handleLifecycleEvent(Lifecycle.Event.ON_START);
       registry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
       return registry;
   }

   @Override
   publicLifecyclegetLifecycle(){
       return mRegistry;
   }
};

可以看到, observeForeverObserver 注册了在一个永远处于 RESUMED 的 LifecycleOwner 中,所以通过 observeForever 注册的 Observer 需要通过 removeObserver 来取消数据变化的监听。

总结

至此,我们已经明白 LiveData 主要是通过 LifecycleBoundObserverLifecycle 结合来控制数据的分发。

LiveData的代码比 Lifecycle 要简单得多,主要是有了 Lifecycle 部分的分析作为基础,看起来很轻松。因为简单,所以文章记录的时候流水账比较严重,本来不打算发的 _(:з」∠)_ 不过写都写了,扔出来占个位置吧。


以上所述就是小编给大家介绍的《LiveData 源码分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming Concurrency on the JVM

Programming Concurrency on the JVM

Venkat Subramaniam / The Pragmatic Bookshelf / 2011-6-1 / USD 35.00

Concurrency on the Java platform has evolved, from the synchronization model of JDK to software transactional memory (STM) and actor-based concurrency. This book is the first to show you all these con......一起来看看 《Programming Concurrency on the JVM》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具