Android livedata 源码解剖

994 阅读13分钟
原文链接: mp.weixin.qq.com

说在前面

本次推出 Android Architecture Components 系列文章,目前写好了四篇,主要是关于 lifecycle,livedata 的使用和源码分析,其余的 Navigation, Paging library,Room,WorkMannager 等春节结束之后会更新,欢迎关注我的公众号,有更新的话会第一时间会在公众号上面通知。

Android lifecycle 使用详解

Android LiveData 使用详解

Android lifecyle 源码解剖

Android livedata 源码解剖


前言

在前面三篇博客中,我们已经介绍了 lifecycle 的使用及原理,livedata ,ViewModel 的常用用法,今天,让我们一起来学习 livedata 的原理。

我们先来回顾一下 LiveData 的特点:

LiveData 是一个可以被观察的数据持有类,它可以感知 Activity、Fragment或Service 等组件的生命周期。

  1. 它可以做到在组件处于激活状态的时候才会回调相应的方法,从而刷新相应的 UI。

  2. 不用担心发生内存泄漏

  3. 当 config 导致 activity 重新创建的时候,不需要手动取处理数据的储存和恢复。内部已经帮我们封装好了。

  4. 当 Actiivty 不是处于激活状态的时候,如果你想 livedata setValue 之后立即回调 obsever 的 onChange 方法,而不是等到 Activity 处于激活状态的时候才回调 obsever 的 onChange 方法,你可以使用 observeForever 方法,但是你必须在 onDestroy 的时候 removeObserver

下面,让我们一步步解剖它


原理分析

我们知道 livedata 的使用很简单,它是采用观察者模式实现的

  1. 添加观察者

  2. 在数据改变的时候设置 value,这样会回调 Observer 的 onChanged 方法

1MutableLiveData<String> nameEvent = mTestViewModel.getNameEvent();2nameEvent.observe(this, new Observer<String>() {3    @Override4    public void onChanged(@Nullable String s) {5        Log.i(TAG, "onChanged: s = " + s);6        mTvName.setText(s);7    }8});

observe 方法

 1@MainThread 2public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) { 3    // 判断是否已经销毁 4    if (owner.getLifecycle().getCurrentState() == DESTROYED) { 5        // ignore 6        return; 7    } 8    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); 9    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);10    // observer 已经添加过了,并且缓存的 observer 跟 owner 的 observer 不一致,状态异常,抛出异常11    if (existing != null && !existing.isAttachedTo(owner)) {12        throw new IllegalArgumentException("Cannot add the same observer"13                + " with different lifecycles");14    }15    // 已经添加过 Observer 了,返回回去16    if (existing != null) {17        return;18    }1920    // 添加 observer21    owner.getLifecycle().addObserver(wrapper);22}

首先,我们先来看一下它的 observe 方法,首先通过 owner.getLifecycle().getCurrentState() 获取状态,判断是否已经被销毁,如果已经被销毁,直接返回。接着用 LifecycleBoundObserver 包装起来。然后从缓存的 mObservers 中读取 observer,如果有,证明已经添加过了。

observe 方法,小结起来就是

  1. 判断是否已经销毁,如果销毁,直接移除

  2. 用 LifecycleBoundObserver 包装传递进来的 observer

  3. 是否已经添加过,添加过,直接返回

  4. 将包装后的 LifecycleBoundObserver 添加进去

因此,当 owner 你(Activity 或者 fragment) 生命周期变化的时候,会回调 LifecycleBoundObserver 的 onStateChanged 方法,onStateChanged 方法又会回调 observer 的 onChange 方法

LifecycleBoundObserver

 1class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { 2    @NonNull final LifecycleOwner mOwner; 3 4    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) { 5        super(observer); 6        mOwner = owner; 7    } 8 9    @Override10    boolean shouldBeActive() {11        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);12    }1314    @Override15    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {16        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {17            removeObserver(mObserver);18            return;19        }20        activeStateChanged(shouldBeActive());21    }2223    @Override24    boolean isAttachedTo(LifecycleOwner owner) {25        return mOwner == owner;26    }2728    @Override29    void detachObserver() {30        mOwner.getLifecycle().removeObserver(this);31    }323334}

我们来看一下 LifecycleBoundObserver,继承 ObserverWrapper,实现了 GenericLifecycleObserver 接口。而 GenericLifecycleObserver 接口又实现了 LifecycleObserver 接口。 它包装了我们外部的 observer,有点类似于代理模式。

GenericLifecycleObserver#onStateChanged

Activity 回调周期变化的时候,会回调 onStateChanged ,会先判断 mOwner.getLifecycle().getCurrentState() 是否已经 destroy 了,如果。已经 destroy,直接移除观察者。这也就是为什么我们不需要手动 remove observer 的原因

如果不是销毁状态,会调用 activeStateChanged 方法 ,携带的参数为 shouldBeActive() 返回的值。而当 lifecycle 的 state 为 started 或者 resume 的时候,shouldBeActive 方法的返回值为 true,即表示激活。

 1    void activeStateChanged(boolean newActive) { 2    if (newActive == mActive) { 3        return; 4    } 5    // immediately set active state, so we'd never dispatch anything to inactive 6    // owner 7    mActive = newActive; 8    boolean wasInactive = LiveData.this.mActiveCount == 0; 9    LiveData.this.mActiveCount += mActive ? 1 : -1;10    if (wasInactive && mActive) {11        onActive();12    }13    if (LiveData.this.mActiveCount == 0 && !mActive) {14        onInactive();15    }16    if (mActive) {17        dispatchingValue(this);18    }

}

activeStateChanged 方法中,,当 newActive 为 true,并且不等于上一次的值,会增加 LiveData 的 mActiveCount 计数。接着可以看到,onActive 会在 mActiveCount 为 1 时触发,onInactive 方法则只会在 mActiveCount 为 0 时触发。即回调 onActive 方法的时候活跃的 observer 恰好为 1,回调 onInactive 方法的时候,没有一个 Observer 处于激活状态。

当 mActive 为 true 时,会促发 dispatchingValue 方法。

dispatchingValue

 1private void dispatchingValue(@Nullable ObserverWrapper initiator) { 2   // 如果正在处理,直接返回 3    if (mDispatchingValue) { 4        mDispatchInvalidated = true; 5        return; 6    } 7    mDispatchingValue = true; 8 9    do {10        mDispatchInvalidated = false;11        // initiator 不为 null,调用 considerNotify 方法12        if (initiator != null) {13            considerNotify(initiator);14            initiator = null;15        } else { // 为 null 的时候,遍历所有的 obsever,进行分发16            for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =17                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {18                considerNotify(iterator.next().getValue());19                if (mDispatchInvalidated) {20                    break;21                }22            }23        }24    } while (mDispatchInvalidated);25    // 分发完成,设置为 false26    mDispatchingValue = false;27}

其中 mDispatchingValue, mDispatchInvalidated 只在 dispatchingValue 方法中使用,显然这两个变量是为了防止重复分发相同的内容。当 initiator 不为 null,只处理当前 observer,为 null 的时候,遍历所有的 obsever,进行分发

considerNotify 方法

 1private void considerNotify(ObserverWrapper observer) { 2   // 如果状态不是在活跃中,直接返回 3    if (!observer.mActive) { 4        return; 5    } 6    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet. 7    // 8    // we still first check observer.active to keep it as the entrance for events. So even if 9    // the observer moved to an active state, if we've not received that event, we better not10    // notify for a more predictable notification order.11    if (!observer.shouldBeActive()) {12        observer.activeStateChanged(false);13        return;14    }151617    if (observer.mLastVersion >= mVersion) {18    // 数据已经是最新,返回19        return;20    }21    // 将上一次的版本号置为最新版本号22    observer.mLastVersion = mVersion;23    //noinspection unchecked24    // 调用外部的 mObserver 的 onChange 方法25    observer.mObserver.onChanged((T) mData);26}
  1. 如果状态不是在活跃中,直接返回,这也就是为什么当我们的 Activity 处于 onPause, onStop, onDestroy 的时候,不会回调 observer 的 onChange 方法的原因。

  2. 判断数据是否是最新,如果是最新,返回,不处理

  3. 数据不是最新,回调 mObserver.onChanged 方法。并将 mData 传递过去

setValue

1@MainThread2protected void setValue(T value) {3    assertMainThread("setValue");4    mVersion++;5    mData = value;6    dispatchingValue(null);7}

setValue 方法中,首先,断言是主线程,接着 mVersion + 1; 并将 value 赋值给 mData,接着调用 dispatchingValue 方法。dispatchingValue 传递 null,代表处理所有 的 observer。

这个时候如果我们依附的 activity 处于 onPause 或者 onStop 的时候,虽然在 dispatchingValue 方法中直接返回,不会调用 observer 的 onChange 方法。但是当所依附的 activity 重新回到前台的时候,会促发 LifecycleBoundObserver onStateChange 方法,onStateChange 又会调用 dispatchingValue 方法,在该方法中,因为 mLastVersion < mVersion。所以会回调 obsever 的 onChange 方法,这也就是 LiveData 设计得比较巧妙的一个地方

同理,当 activity 处于后台的时候,您多次调用 livedata 的 setValue 方法,最终只会回调 livedata observer 的 onChange 方法一次。

postValue

 1protected void postValue(T value) { 2   boolean postTask; 3   // 锁住 4   synchronized (mDataLock) { 5      // 当前没有人在处理 post 任务 6       postTask = mPendingData == NOT_SET; 7       mPendingData = value; 8   } 9   if (!postTask) {10       return;11   }12   AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);13}14private final Runnable mPostValueRunnable = new Runnable() {15   @Override16   public void run() {17       Object newValue;18       synchronized (mDataLock) {19           newValue = mPendingData;20           // 处理完毕之后将 mPendingData 置为 NOT_SET21           mPendingData = NOT_SET;22       }23       //noinspection unchecked24       setValue((T) newValue);25   }26};
  1. 首先,采用同步机制,通过 postTask = mPendingData == NOT_SET 有没有人在处理任务。 true,没人在处理任务, false ,有人在处理任务,有人在处理任务的话,直接返回

  2. 调用 AppToolkitTaskExecutor.getInstance().postToMainThread 到主线程执行 mPostValueRunnable 任务。

 1@MainThread 2public void observeForever(@NonNull Observer<T> observer) { 3    AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer); 4    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); 5    if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) { 6        throw new IllegalArgumentException("Cannot add the same observer" 7                + " with different lifecycles"); 8    } 9    if (existing != null) {10        return;11    }12    wrapper.activeStateChanged(true);13}1415private class AlwaysActiveObserver extends ObserverWrapper {1617    AlwaysActiveObserver(Observer<T> observer) {18        super(observer);19    }2021    @Override22    boolean shouldBeActive() {23        return true;24    }25}

因为 AlwaysActiveObserver 没有实现 GenericLifecycleObserver 方法接口,所以在 Activity o生命周期变化的时候,不会回调 onStateChange 方法。从而也不会主动 remove 掉 observer。因为我们的 obsever 被 remove 掉是依赖于 Activity 生命周期变化的时候,回调 GenericLifecycleObserver 的 onStateChange 方法。


总结

  1. liveData 当我们 addObserver 的时候,会用 LifecycleBoundObserver 包装 observer,而 LifecycleBoundObserver 可以感应生命周期,当 activity 生命周期变化的时候,如果不是处于激活状态,判断是否需要 remove 生命周期,需要 remove,不需要,直接返回

  2. 当处于激活状态的时候,会判断是不是 mVersion最新版本,不是的话需要将上一次缓存的数据通知相应的 observer,并将 mLastVsersion 置为最新

  3. 当我们调用 setValue 的时候,mVersion +1,如果处于激活状态,直接处理,如果不是处理激活状态,返回,等到下次处于激活状态的时候,在进行相应的处理

  4. 如果你想 livedata setValue 之后立即回调数据,而不是等到生命周期变化的时候才回调数据,你可以使用 observeForever 方法,但是你必须在 onDestroy 的时候 removeObserver。因为 AlwaysActiveObserver 没有实现 GenericLifecycleObserver 接口,不能感应生命周期。

题外话

Android Architecture Components 已经写了四篇文章了,其余的 Navigation, Paging library,Room,WorkMannager 等春节结束之后再更新了,欢迎关注我的公众号,有更新的话会第一时间在公众好上面更新。

Android 技术人