本篇我们来看看 Android 架构组件中的 LiveData
。跟 ViewModel
相比,LiveData
具有生命周期感知能力,也就是说,他把 ViewModel
和 lifecycle 结合了起来。当应用的数据有更新时,一般我们仅希望应用对用户可见时才更新 UI;更进一步,如果应用不可见,我们甚至可以停止数据的更新。这就是所谓的“感知应用的生命周期”。
这里我们主要关注 LiveData
的实现,用法可以参考 Google 的教程 。
添加 Observer 使用 LiveData
时,首先要做的,就是添加一个 Observer<T>
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public interface Observer <T > { void onChanged (@Nullable T t) ; } public abstract class LiveData <T > { public void observe (@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {} public void observeForever (@NonNull Observer<T> observer) {} }
由于 LiveData
是一个 abstract class
,我们不能直接生成他的实例。对于数据的拥有者 ,可以使用 MutableLiveData
:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class MutableLiveData <T > extends LiveData <T > { @Override public void postValue (T value) { super .postValue(value); } @Override public void setValue (T value) { super .setValue(value); } }
所谓数据的拥有者。举个例子,你使用的是 MVP 模式,那么数据就属于 Model 层,另外两层不应该修改数据。
通过让这两个 setter 方法成为 protected
,只要我们给客户返回的是 LiveData
,就不用担心数据会被客户意外修改:
1 2 3 4 5 6 7 8 9 10 class SomeClass extends ViewModel { private final MutableLiveData<Foo> mYourData = new MutableLiveData<>(); public LiveData<Foo> getData () { return mYourData; } }
活用 public
, protected
, private
, default access
和 final
可以让我们的设计意图更加清晰。
现在回到我们的 observe()
方法,observeForever
的实现跟 observe
是类似的,我们就不看了,这里只看 observe()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public abstract class LiveData <T > { public void observe (@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) { if (owner.getLifecycle().getCurrentState() == DESTROYED) { return ; } LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); if (existing != null && !existing.isAttachedTo(owner)) { throw new IllegalArgumentException("Cannot add the same observer" + " with different lifecycles" ); } if (existing != null ) { return ; } owner.getLifecycle().addObserver(wrapper); } }
我们继续看 LifecycleBoundObserver
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 public abstract class LiveData <T > { protected void onActive () {} protected void onInactive () {} private abstract class ObserverWrapper { final Observer<T> mObserver; boolean mActive; int mLastVersion = START_VERSION; ObserverWrapper(Observer<T> observer) { mObserver = observer; } abstract boolean shouldBeActive () ; boolean isAttachedTo (LifecycleOwner owner) { return false ; } void detachObserver () { } void activeStateChanged (boolean newActive) { if (newActive == mActive) { return ; } 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 ); } } } class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) { super (observer); mOwner = owner; } @Override boolean shouldBeActive () { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } @Override public void onStateChanged (LifecycleOwner source, Lifecycle.Event event) { 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 ); } } }
到这里,observer 的注册我们就看完了。下面我们看看如何发布(publish)数据给 LiveData
。
发布修改 要修改 LiveData
,有两种方式:
1 2 3 4 5 6 7 8 public abstract class LiveData <T > { protected void setValue (T value) ; protected void postValue (T value) ; }
setValue
比较简单,我们先看 setValue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public abstract class LiveData <T > { @MainThread protected void setValue (T value) { assertMainThread("setValue" ); mVersion++; mData = value; dispatchingValue(null ); } private void dispatchingValue (@Nullable ObserverWrapper 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>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break ; } } } } while (mDispatchInvalidated); mDispatchingValue = false ; } }
看过我那篇 lifecycle 源码分析的读者应该对 dispatchingValue
处理循环调用的方式很熟悉了。以这里为例,为了防止循环调用,我们在调用客户代码前先置位一个标志(mDispatchingValue
),结束后再设为 false
。如果在回调里面又触发了这个方法,可以通过 mDispatchingValue
来检测。
检测到循环调用后,再设置第二个标志(mDispatchInvalidated
),然后返回。返回又会回到之前的调用,前一个调用通过检查 mDispatchInvalidated
,知道数据被修改,于是开始一轮新的迭代。
下面是 considerNotify
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public abstract class LiveData <T > { private void considerNotify (ObserverWrapper observer) { if (!observer.mActive) { return ; } if (!observer.shouldBeActive()) { observer.activeStateChanged(false ); return ; } if (observer.mLastVersion >= mVersion) { return ; } observer.mLastVersion = mVersion; observer.mObserver.onChanged((T) mData); } }
看完了 setValue
,postValue
对我们来说就很简单了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public abstract class LiveData <T > { private volatile Object mPendingData = NOT_SET; private final Runnable mPostValueRunnable = new Runnable() { @Override public void run () { Object newValue; synchronized (mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } setValue((T) newValue); } }; protected void postValue (T value) { boolean postTask; synchronized (mDataLock) { postTask = mPendingData == NOT_SET; mPendingData = value; } if (!postTask) { return ; } ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); } }
LiveData
的核心代码我们已经看完了,其实他的实现也挺简单的,对吧?
总结 关于 LiveData
,有两个值得我们学习的,一个是循环调用的处理,另一个是 mVersion
的使用。关于 mVersion
,这里再举一个之前工作中遇到的例子。在后台线程对数据进行持久化的时候(这个线程拷贝了一份数据),数据还有可能会被更新。为了判断所保存的数据是不是最新的,我当时的做法就是引入一个类似 mVersion
的东西,每次修改数据,都把 mVersion
加 1。通过比较 mVersion
和所保存的数据的 version,就能够知道是不是保存了最新的数据(当然,更好的做法是告诉后台线程数据已经修改,让他重新拿一次数据)。