前言 Android Jetpack 常用组件 Lifecycle、ViewModel、LiveData 原理分析。
基石 Lifecycle
首先可以总体看一下涉及到 Lifecycle 组件的主要类,下面就其中的细节慢慢展开。
Lifecycle 有什么用? Lifecycle 是具备宿主生命周期感知能力的组件。它能持有组件(如 Activity 或 Fragment)生命周期状态的信息,并且允许其他观察者监听宿主的状态。它也是 Jetpack 组件库的的核心基础,LiveData , ViewModel 组件等也都是基于它来实现的。
Lifecycle 怎么用? 其实关于 Lifecycle 怎么用本质上是在说,我们改如何实现 addObserver() 中的这个 observer .
1 lifecycle.addObserver(EasyObserver())
从上面的概览图出发,结合 LifecycleObserver 及其子类,实现一个 Lifecycle 的观察者可以有三种方式。
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 class EasyObserver : LifecycleObserver ,DefaultLifecycleObserver , LifecycleEventObserver { @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun foo () {} override fun onCreate (owner: LifecycleOwner ) { super .onCreate(owner) Log.d(LIFECYCLE_TAG, "onCreate() called with: owner = $owner " ) } override fun onResume (owner: LifecycleOwner ) { super .onResume(owner) val value = owner.lifecycle.currentState Log.d(LIFECYCLE_TAG, "onResume() called onResume, currentState =$value " ) if (value.isAtLeast(Lifecycle.State.STARTED)) { Log.d(LIFECYCLE_TAG, "atLeast started" ) } } override fun onPause (owner: LifecycleOwner ) { super .onPause(owner) Log.d(LIFECYCLE_TAG, "onPause() called with: owner = $owner " ) } override fun onStateChanged (source: LifecycleOwner , event: Lifecycle .Event ) { Log.d(LIFECYCLE_TAG, "onStateChanged() called with: source = $source , event = $event " ) } }
直接实现 LifecycleObserver 接口,给自定义方法添加 OnLifecycleEvent 注解,在相应的生命周期方法触发方法调用。
直接实现 DefaultLifecycleObserver 接口, 覆写生命周期方法
直接实现 LifecycleEventObserver 接口,在其 onStateChanged 方法中按参数实现对应生命周期的功能。
记得一定要在实现了 LifecycleOwner 的组件中注册这个 LifecycleObserver ,否则谁来给他分发生命周期呢?
Activity/Fragment 是如何实现 Lifecycle 的 ? 关于如何实现 Lifecycle ,我们可以从被观察者和观察者两侧分别展开分析。
被观察的宿主 首先是被观察者,也就是实现了 LifecycleOwner 接口,表示自己是可以被观察的宿主的类。在这一点上Activity 和 Fragment 本质上是相似的,都是通过借助组件自身的生命周期(Activity 早期版本依赖 ReportFragment) ,通过 LifecycleRegistry 对所有的观察者进行生命周期的分发。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class ComponentActivity extends Activity implements LifecycleOwner { private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this ); @NonNull @Override public Lifecycle getLifecycle () { return mLifecycleRegistry; } protected void onCreate (Bundle bundle) { super .onCreate(savedInstanceState); ReportFragment.injectIfNeededIn(this ); }
这里的实现其实跟 Fragment 中的源码是一样的,在各个生命周期方法内利用 LifecycleRegistry 派发相应的 Lifecycle.Event 事件给每个观察者
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 class ReportFragment extends Fragment { public static void injectIfNeededIn (Activity activity) { android.app.FragmentManager manager = activity.getFragmentManager(); if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null ) { manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); } } @Override public void onStart () { super .onStart(); dispatch(Lifecycle.Event.ON_START); } @Override public void onResume () { super .onResume(); dispatch(Lifecycle.Event.ON_RESUME); } @Override public void onPause () { super .onPause(); dispatch(Lifecycle.Event.ON_PAUSE); } @Override public void onDestroy () { super .onDestroy(); dispatch(Lifecycle.Event.ON_DESTROY); } private void dispatch (Lifecycle.Event event) { Lifecycle lifecycle = activity.getLifecycle(); if (lifecycle instanceof LifecycleRegistry) { ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); } }
LifecycleRegistry 在分发事件的时候会涉及到两个概念:
这里其实可以类比线程的生命周期状态。注意到
ON_CREATE 和 ON_STOP 这两个 event 都可以使 state 处于 CREATED;
ON_START 和 ON_PAUSE 这两个 event 都可以使 state 处于 STARTED
这里比较微妙,可以多思考一下。我们可以看一下在 LifecycRegistry 中 handleLifecycleEvent
是如何处理的。
handleLifecycleEvent 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 public void handleLifecycleEvent (@NonNull Lifecycle.Event event) { State next = getStateAfter(event); moveToState(next); } private void sync () { while (!isSynced()) { if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0 ) { backwardPass(lifecycleOwner); } Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest(); if (!mNewEventOccurred && newest != null && mState.compareTo(newest.getValue().mState) > 0 ) { forwardPass(lifecycleOwner); } } }
说完了生命周期主动分发的场景,我们再来看看观察者注册的玄机.
addObserver 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 public void addObserver (@NonNull LifecycleObserver observer) { State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; ObserverWithState statefulObserver = new ObserverWithState(observer, initialState); ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver); if (previous != null ) { return ; } State targetState = calculateTargetState(observer); while ((statefulObserver.mState.compareTo(targetState) < 0 && mObserverMap.contains(observer))) { pushParentState(statefulObserver.mState); statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState)); targetState = calculateTargetState(observer); } }
Lifecycle 的特性我们在任意生命周期方法内注册观察者都能接收到完成的生命周期事件,比如在onResume 中注册一个观察者,它会依次收到:
1 LifecycleEvent.onCreate -> LifecycleEvent.onStart -> LifecycleEvent.onResume
可以看到在 addObserver 中,会根据当将当前 oberver 和其所处的状态包装成一个 ObserverWithState .我们看一下为什么要这么做。
ObserverWithState 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 static class ObserverWithState { State mState; LifecycleEventObserver mLifecycleObserver; ObserverWithState(LifecycleObserver observer, State initialState) { mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer); mState = initialState; } void dispatchEvent (LifecycleOwner owner, Event event) { State newState = event.getTargetState(); mState = min(mState, newState); mLifecycleObserver.onStateChanged(owner, event); mState = newState; } }
这里有个细节可以注意一下,构造函数 observer 是 LifecycleObserver 类型的,而内部的 mLifecycleObserver 是 LifecycleEventObserver 类型的,是其子类。一开始我们说了,创建 observer 时可以有多种方式。 而到了这里,都会统一成 LifecycleEventObserver 这种实现进行处理。
观察者是如何实现统一的 至于 Lifecycling.lifecycleEventObserver 是如何将使用注解、实现 DefaultLifecycleObserver 等方式统一成 LifecycleEventObserver ,以及注解是如何生效的之类的内容,可以参考这篇“终于懂了“系列:Jetpack AAC完整解析,Lifecycle 完全掌握 ,分析的很详细了。
ProcessLifecycleOwner 使用ProcessLifecycleOwner可以直接获取应用前后台切换状态。其实内部实现就是统计 Activity 的状态,自己实现也是可以的。
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 public class MyApplication extends Application { @Override public void onCreate () { super .onCreate(); ProcessLifecycleOwner.get().getLifecycle().addObserver(new ApplicationLifecycleObserver()); } private static class ApplicationLifecycleObserver implements LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_START) private void onAppForeground () { Log.w(TAG, "ApplicationObserver: app moved to foreground" ); } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) private void onAppBackground () { Log.w(TAG, "ApplicationObserver: app moved to background" ); } } }
ViewModel ViewModel 作为 Jetpack 常用的组件,最重要的原因就是其生命周期比 Activity、Fragment 长的这一点吧。
两点优势:
存储的数据只能当页面因为配置变更导致的销毁再重建时可复用
实现跨页面不同的(Activity)的数据共享,Application 内创建的 ViewModel ,同 Activity 多 Fragment 共享 ViewModel
回想我们创建 ViewModel 实例的代码
1 val fooViewModel = ViewModelProvider(this ).get (FooViewModel::class .java)
1 2 3 4 5 6 7 8 9 public ViewModelProvider (@NonNull ViewModelStoreOwner owner) { this (owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory() : NewInstanceFactory.getInstance()); } public ViewModelProvider (@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) { this (owner.getViewModelStore(), factory); }
从图示和代码可看到,ViewModelProvider 内部是靠着 ViewModelStore 和 Factory 创建和管理内部的 ViewModel 实例。
1 2 3 4 5 6 7 8 9 10 11 public <T extends ViewModel> T get (@NonNull String key, @NonNull Class<T> modelClass) { ViewModel viewModel = mViewModelStore.get(key); if (mFactory instanceof KeyedFactory) { viewModel = ((KeyedFactory) mFactory).create(key, modelClass); } else { viewModel = mFactory.create(modelClass); } mViewModelStore.put(key, viewModel); return (T) viewModel; }
因此,我们可以确定说,要在 Activity(Fragment) 销毁的时候保证 ViewModel 的存活,其实就是要保证 ViewModelStore 的存活,而 ViewModelStore 又是由 ViewModelStoreOwner 提供的,因此。问题就来到了 ViewModelStoreOwner 是如何维护 ViewModelStore 的。
可以看到 Activity 和 Fragment 都以不同的方式实现了 ViewModelStoreOwner。 Activity 是直接实现接口,而 Fragment 是通过代理实现。下面就来看看其中奥秘,为什么 Activity 实例重建的时候依旧可以保持之前的 ViewModelStore 可用。
Activity 如何维护 ViewModelStore 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 class ComponentActivity extends ViewModelStoreOwner { static final class NonConfigurationInstances { Object custom; ViewModelStore viewModelStore; } public ViewModelStore getViewModelStore () { if (mViewModelStore == null ) { NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc != null ) { mViewModelStore = nc.viewModelStore; } if (mViewModelStore == null ) { mViewModelStore = new ViewModelStore(); } } return mViewModelStore; } } }
onRetainNonConfigurationInstance
因系统原因页面被回收时,会触发该方法,所以 viewModelStore 对象此时会被存储在 NonConfigurationInstance 中。在页面恢复重建时,会再次把这个 NonConfigurationInstance 对象传递到新的Activity 中实现对象复用。
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 class ComponentActivity {public final Object onRetainNonConfigurationInstance () { Object custom = onRetainCustomNonConfigurationInstance(); ViewModelStore viewModelStore = mViewModelStore; if (viewModelStore == null ) { NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc != null ) { viewModelStore = nc.viewModelStore; } } if (viewModelStore == null && custom == null ) { return null ; } NonConfigurationInstances nci = new NonConfigurationInstances(); nci.custom = custom; nci.viewModelStore = viewModelStore; return nci; } }
注意这里的 ViewModelStore 可以被保存的条件,也就是 onRetainNonConfigurationInstance 调用的条件: due to a configuration change ,手机内存不足及突然没电的场景是不符合的。 关于 ViewModel 保存数据更多的细节可以看看这个问题 每日一问 | ViewModel 在什么情况下的「销毁重建」能够对数据进行无缝恢复?
Activity onRetainNonConfigurationInstance 调用时机 ?
Called by the system, as part of destroying an 阅读更多
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 class Activity { public Object onRetainNonConfigurationInstance () { return null ; } }
ViewModel vs onSaveIntanceState
onSaveIntanceState 只能存储轻量级的 key-value 键值对数据,非配置变更导致的页面被回收时才会触发,此时数据存储在 ActivityRecord 中;
ViewModel 可以存放任意 Object 数据,因配置变更导致的页面被回收才有效。此时存在ActivityThread#ActivityClientRecord 中。
SavedState
ViewModel 只能当页面因配置变更而重建时才能复用,但如果是内存不足或者电量不足等系统原因导致的页面被回收时 ViewModel 是不会被复用的
SavedState 能够帮助开发者在 ViewModel 中处理 Activity 和 fragment 状态保存和恢复。
1 api 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
LiveData
LiveData 有什么用? LiveData 组件是 Jetpack 新推出的基于观察者的消息订阅/分发组件,具有宿主(Activity、Fragment)生命周期感知能力,这种感知能力可确保 LiveData 仅分发消息给处于活跃状态(宿主处于 started,resumed 状态)的观察者,即只有处于活跃状态的观察者才能收到消息 。
LiveData 核心原理 相比 Lifecycle 和 ViewModel,LiveData 整体的实现更加的内聚,所有逻辑基本都统一在 LiveData 内实现。
我们就从上面图中列出的有点出发,看看 LiveData 是如何实现数据符合页面状态、不需要手动处理生命周期、数据保持最新状态 等这些功能的。
添加观察者 从我们日常使用 LiveData 的场景出发,看看 observe 的实现。
1 2 3 4 fooViewModel.foo.observe(viewLifecycleOwner, { text.text = "result is $it " Log.e(TAG, "$it " ) })
LiveData.observe 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @MainThread public void observe (@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { assertMainThread("observe" ); 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); }
首先会把 LifecycleOwner 和 observer 包装成一个 LifecycleBoundObserver
。 结合上面 UML 图整体的代码架构,可以看到 LifecycleBoundObserver 本质上是一个 ObserverWrapper
。这里的思路和 LifecycleRegistry 的实现非常相似,就是把观察这和其所处的状态做一个封装,便于后面统一维护和更新。
ObserverWrapper.class 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 private abstract class ObserverWrapper { final Observer<? super T> mObserver; boolean mActive; int mLastVersion = START_VERSION; ObserverWrapper(Observer<? super T> observer) { mObserver = observer; } ... } class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) { super (observer); mOwner = owner; } @Override public void onStateChanged (@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) { 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(); } } }
这里就比较有意思,ObserverWrapper
顾名思义,就是包装了一个 Observer. 同时在其内部维护了 mActive 和 mLastVersion 两个成员变量,用于记录当前 Observer 的状态。
LifecycleBoundObserver
(这个命名很贴切,值得学习) 在 ObserverWrapper
的基础上又扩展添加了 LifecycleOwner
。也就是说一个 LifecycleBoundObserver 的实例,做为一个观察者,即有自身的状态,又会感知组件(也就是 Activity/Fragment)的生命周期。这就有意思了。
可以看到在其 onStateChanged
方法中,观察者所在的组件的 state 处于 DESTORY 的时候,会主动移除观察者。就是这么简单,实现了不用处理生命周期,自动实现解除注册的功能。
而如果 currentState 不是 DESTORY 的时候,那么就会进行状态的变更。
1 2 3 4 5 6 7 8 9 10 11 @Override boolean shouldBeActive () { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } Lifecycle.State prevState = null ; while (prevState != currentState) { prevState = currentState; activeStateChanged(shouldBeActive()); currentState = mOwner.getLifecycle().getCurrentState(); }
在 while 循环中,如果当前的 state 小于 STARTED .在枚举中,变量的大小是暗含在其声明顺序当中的。
1 2 3 4 5 6 7 8 9 10 11 12 public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; public boolean isAtLeast (@NonNull State state) { return compareTo(state) >= 0 ; } }
因此,这里 isAtLeast 返回为 ture,就是说当前状态是 STARTED 或 RESUMED。否则就是 false. 在来看 activeStateChanged
ObserverWrapper.activeStateChanged 1 2 3 4 5 6 7 8 9 10 11 12 13 void activeStateChanged (boolean newActive) { if (newActive == mActive) { return ; } mActive = newActive; changeActiveCounter(mActive ? 1 : -1 ); if (mActive) { dispatchingValue(this ); } }
首先就是对比状态的变化,也就是说只有 newActive 的值发生变化,才会继续执行,否则直接 return. 这种什么意思呢? 就是说,如果状态从 STARTED–> RESUMED 或者是 RESUMED->STARTED 。那么 shouldBeActive
始终是 true 。不会变更。简单来说,以 STARTED 为分界线的话,状态在 STARTED、RESUMED 之间变化 或者完全在 DESTROYED、INITIALIZED、CREATED 之间切换时,是不会 shouldBeActive 返回值是不会变化的。而只有当状态越过了这条分界线,才会变化。就会执行 changeActiveCounter
方法。
而只有 mActive 为 TRUE 的是,也就是状态绝对的处于 STARTED/RESUMED 的时候,才会执行 dispatchingValue 进行数据的分发。这样就做到了数据始终保持最新,而且也不会在应用处于后台的时候更新数据。
这里还有一个点,就是 LiveData 所谓的黏性事件,试想,如果我们在添加观察者之前对 LiveData 进行了 setValue/postValue 的操作,那么一旦这里 mActive 的条件成立,就会接收到之前的值,首次添加的 Observer 其 mLastVersion = START_VERSION ,一定是比变更过的当前 LiveData 小的 ,那么一定会进行触发 Observer 的更新(这里的原因,后面有解释)。
更新数据 setValue/postValue 说完了添加观察者,我们再来看看数据更新,首先看 setValue。
setValue 1 2 3 4 5 6 7 @MainThread protected void setValue (T value) { assertMainThread("setValue" ); mVersion++; mData = value; dispatchingValue(null ); }
dispatchingValue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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<? super T>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break ; } } } } while (mDispatchInvalidated); mDispatchingValue = false ; }
setValue 和 dispatchingValue 整体的逻辑还是比较简单的,就是做一下去重,避免重复发送。 注意,initiator 的类型是 ObserverWrapper 。 当然,这里如果是主动调用 setValue ,那么参数 initiator 为null,就需要遍历所有当前 LiveData 的观察者调用 considerNotify 。 如果是因为当前 LiveData 的状态变更,也就是注册的时候需要变化,那么对当前这一个 Observer 分发就可以了。
最后看 considerNotify 。
considerNotify 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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); }
considerNotify
的实现虽然看起来很简单,但是每一个行都大有玄机。
observer.mActive : 添加观察者的阶段,我们就说过了,如果组件处于不可见的状态,那么他的 state 会小于 STARTED ,因此,mActive 就是 false 。 此时,调用 setValue 就会直接返回。因为,这样边保证了页面处于非活动的状态,主动通知也不会想观察者发送数据。
observer.shouldBeActive() 再次检测,如果代码执行到这里的时候,state 依然变化了,那么就更像 state ,同时返回。
数据分发
1 2 3 4 5 if (observer.mLastVersion >= mVersion) { return ; } observer.mLastVersion = mVersion; observer.mObserver.onChanged((T) mData);
这里需要整体来看,如果当前 if 条件为 FALSE。走到了下一行,那么当前这一个 Observer 的 mLastVersion 就和 mVersion 同步了。同时调用 Observer.onChanged 方法,完成数据回调。同时,在整个 LiveData 内部,可以对 mVersion 进行写操作的只有 LiveData 构造函数和 setValue 方法。因此,这里的逻辑就很清楚了,调用 setValue 对 Observer 更新值之后,如果由于其他原因再次发生 considerNotify 。那么只要 mVersion 的值没有更新,那么就不会在调用 onChanged 了,因为数据 mData 肯定没有更新,回调回去的值一定是相同的,那么对于更新 UI 来说就没有意义了,虽然在某些场景下可能有意义。
postValue 1 2 3 4 5 6 7 8 9 10 11 protected void postValue (T value) { boolean postTask; synchronized (mDataLock) { postTask = mPendingData == NOT_SET; mPendingData = value; } if (!postTask) { return ; } ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); }
关于 setValue 和 postValue 的区别应该很简单了。这里我们可以想一下,连续多次调用 setValue 和 postValue 会有什么区别?
首先对于 setValue 是在 UI 线程执行,那么他一定会保证每一次的调用。因此,观察者一定可以接收到所有的值。但是对于 postValue 来说就不一样了,首先了多线程调用的 synchronized 锁,即便过了锁这一关,mPendingData
在没有其他地方更新的情况下,postTaks 就是 false.因此整体逻辑直接就 return 了。那么什么时候会更新 mPendingData
呢? 我们看 `mPostValueRunnable。
mPostValueRunnable
1 2 3 4 5 6 7 8 9 10 11 12 private final Runnable mPostValueRunnable = new Runnable() { @SuppressWarnings("unchecked") @Override public void run () { Object newValue; synchronized (mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } setValue((T) newValue); } };
真相只有一个,可以看到只有这个 mPostValueRunnable 被执行了,才会将 mPendingData
初始化。同时可以看到这里的 run 方法里使用了和 postValue 里相同对象锁。也就是说,要么对进行赋值,要么执行。这也是必须的,否则 newValue 的值就可能不是最新的了,就会发生数据丢失的问题。最后,还是调用 setValue 执行具体的数据更新。 但是,从这一点,可以看到连续的调用 postValue 。Observer 获取的值并不会是连续的。
我们可以简单试下
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 class FooViewModel (application: Application) : AndroidViewModel(application) { val mainValue = MutableLiveData(0L ) val threadValue = MutableLiveData(0L ) fun doUpdate () { Observable.intervalRange(1 ,100 ,1 ,1 ,TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .doOnNext { mainValue.value = it } .subscribe() Observable.intervalRange(1 ,100 ,1 ,1 ,TimeUnit.MILLISECONDS) .doOnNext { threadValue.postValue(it) } .subscribe() } } private fun testSetAndPost () { fooViewModel.mainValue.observe(viewLifecycleOwner, { Log.e("testSetAndPost" , "mainValue =$it " ) }) fooViewModel.threadValue.observe(viewLifecycleOwner, { Log.e("testSetAndPost" , "threadValue =$it " ) }) fooViewModel.doUpdate() }
这里暂时忽略 RxJava 的相关问题,只是为了方便演示。我们分别在 主线程和子线程更新 mainValue
和 threadValue
. 然后在任何实现了 viewLifecycleOwner 的组件内观察他们的值。多次执行,可以发现输出结果和我们上面的结论是一致的。
某一种输出
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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 E/testSetAndPost: mainValue =0 E/testSetAndPost: threadValue =0 E/testSetAndPost: mainValue =1 E/testSetAndPost: mainValue =2 E/testSetAndPost: mainValue =3 E/testSetAndPost: mainValue =4 E/testSetAndPost: mainValue =5 E/testSetAndPost: mainValue =6 E/testSetAndPost: mainValue =7 E/testSetAndPost: mainValue =8 E/testSetAndPost: mainValue =9 E/testSetAndPost: mainValue =10 E/testSetAndPost: mainValue =11 E/testSetAndPost: mainValue =12 E/testSetAndPost: mainValue =13 E/testSetAndPost: mainValue =14 E/testSetAndPost: mainValue =15 E/testSetAndPost: mainValue =16 E/testSetAndPost: mainValue =17 E/testSetAndPost: mainValue =18 E/testSetAndPost: mainValue =19 E/testSetAndPost: mainValue =20 E/testSetAndPost: mainValue =21 E/testSetAndPost: mainValue =22 E/testSetAndPost: mainValue =23 E/testSetAndPost: mainValue =24 E/testSetAndPost: mainValue =25 E/testSetAndPost: mainValue =26 E/testSetAndPost: mainValue =27 E/testSetAndPost: mainValue =28 E/testSetAndPost: mainValue =29 E/testSetAndPost: mainValue =30 E/testSetAndPost: mainValue =31 E/testSetAndPost: mainValue =32 E/testSetAndPost: mainValue =33 E/testSetAndPost: mainValue =34 E/testSetAndPost: mainValue =35 E/testSetAndPost: mainValue =36 E/testSetAndPost: mainValue =37 E/testSetAndPost: mainValue =38 E/testSetAndPost: mainValue =39 E/testSetAndPost: mainValue =40 E/testSetAndPost: mainValue =41 E/testSetAndPost: mainValue =42 E/testSetAndPost: mainValue =43 E/testSetAndPost: mainValue =44 E/testSetAndPost: mainValue =45 E/testSetAndPost: mainValue =46 E/testSetAndPost: mainValue =47 E/testSetAndPost: mainValue =48 E/testSetAndPost: mainValue =49 E/testSetAndPost: mainValue =50 E/testSetAndPost: mainValue =51 E/testSetAndPost: mainValue =52 E/testSetAndPost: mainValue =53 E/testSetAndPost: mainValue =54 E/testSetAndPost: mainValue =55 E/testSetAndPost: mainValue =56 E/testSetAndPost: mainValue =57 E/testSetAndPost: mainValue =58 E/testSetAndPost: mainValue =59 E/testSetAndPost: mainValue =60 E/testSetAndPost: mainValue =61 E/testSetAndPost: mainValue =62 E/testSetAndPost: mainValue =63 E/testSetAndPost: mainValue =64 E/testSetAndPost: mainValue =65 E/testSetAndPost: mainValue =66 E/testSetAndPost: mainValue =67 E/testSetAndPost: mainValue =68 E/testSetAndPost: mainValue =69 E/testSetAndPost: mainValue =70 E/testSetAndPost: mainValue =71 E/testSetAndPost: mainValue =72 E/testSetAndPost: mainValue =73 E/testSetAndPost: mainValue =74 E/testSetAndPost: mainValue =75 E/testSetAndPost: mainValue =76 E/testSetAndPost: mainValue =77 E/testSetAndPost: threadValue =76 E/testSetAndPost: threadValue =77 E/testSetAndPost: mainValue =78 E/testSetAndPost: threadValue =78 E/testSetAndPost: mainValue =79 E/testSetAndPost: threadValue =79 E/testSetAndPost: mainValue =80 E/testSetAndPost: threadValue =80 E/testSetAndPost: mainValue =81 E/testSetAndPost: threadValue =81 E/testSetAndPost: mainValue =82 E/testSetAndPost: threadValue =82 E/testSetAndPost: mainValue =83 E/testSetAndPost: threadValue =83 E/testSetAndPost: mainValue =84 E/testSetAndPost: threadValue =84 E/testSetAndPost: mainValue =85 E/testSetAndPost: threadValue =85 E/testSetAndPost: mainValue =86 E/testSetAndPost: threadValue =86 E/testSetAndPost: mainValue =87 E/testSetAndPost: threadValue =87 E/testSetAndPost: mainValue =88 E/testSetAndPost: threadValue =88 E/testSetAndPost: mainValue =89 E/testSetAndPost: threadValue =89 E/testSetAndPost: mainValue =90 E/testSetAndPost: threadValue =90 E/testSetAndPost: mainValue =91 E/testSetAndPost: threadValue =91 E/testSetAndPost: mainValue =92 E/testSetAndPost: threadValue =92 E/testSetAndPost: mainValue =93 E/testSetAndPost: threadValue =93 E/testSetAndPost: mainValue =94 E/testSetAndPost: threadValue =94 E/testSetAndPost: mainValue =95 E/testSetAndPost: threadValue =95 E/testSetAndPost: mainValue =96 E/testSetAndPost: threadValue =96 E/testSetAndPost: mainValue =97 E/testSetAndPost: threadValue =97 E/testSetAndPost: mainValue =98 E/testSetAndPost: threadValue =98 E/testSetAndPost: mainValue =99 E/testSetAndPost: threadValue =99 E/testSetAndPost: mainValue =100 E/testSetAndPost: threadValue =100
LiveData 扩展 这里就 LiveData 自身的特点做一些延伸和拓展。
取消黏性事件 我们知道 LiveData 是支持黏性事件的。但凡事有利有弊,这样的特性在某些条件下是feature,但在另外一些场景下就变成了问题。下面我们看看如何实现一个更加灵活的 LiveData。
至于黏性事件的原因上面已经分析过了,简单来说,就是新注册的 Observer 其内部的 mLastVersion 小于 LiveData 自身的 mVersion 。如果我们在注册的时候,可以把两者对其,那不就 OK 了吗?具体怎么做呢?首先 ObserverWrapper
内的 mLastVersion 是保内私有的。同时也没有提供在初始化时进行赋值的接口,因此我们是无法直接进行访问的。简单粗暴一些,可以通过反射的方式强行修改这个字段。但是,这样不够优雅,其实我们可以通过代理模式解决这个问题。 version 无法对齐,那我们就手动对齐。
这里我们分别自定义 Observer 和 LiveData ,其中在 PureLiveData
中我们自己维护一个 mVersion ,自定义方法代理 setValue/postValue。同时自定义 Observer,在 PureObserver
中通过自定义的 PureLiveData
中的版本和 stick 字段,决定是否在注册观察者的阶段进行值的分发。
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 class PureObserver <T > ( val data : PureLiveData<T>, val stick: Boolean = false , val observer: Observer<in T> ) : Observer<T> { private var version = data .mVersion override fun onChanged (t: T ) { if (version >= data .mVersion) { if (stick && data .mPureData != null ) { observer.onChanged(data .mPureData) } return } version = data .mVersion observer.onChanged(data .mPureData) } } class PureLiveData <T > : LiveData <T > () { internal var mPureData: T? = null internal var mVersion = 0 fun setData (t: T ) { this .mPureData = t super .setValue(t) } fun postData (t: T ) { this .mPureData = t super .postValue(t) } override fun setValue (value: T ) { mVersion++ super .setValue(value) } override fun postValue (value: T ) { mVersion++ super .postValue(value) } override fun observe (owner: LifecycleOwner , observer: Observer <in T >) { observePure(owner, observer, false ) } fun observePure (owner: LifecycleOwner , observer: Observer <in T >, stick: Boolean ) { super .observe(owner, PureObserver(this , stick, observer)) } }
总结 好了,Jetpack 最常用的几个组件暂时就分析这么多。可以看到 Lifecycle/ViewModel/LiveData 的源码实现是非常巧妙的,尤其是 LiveData,有很多值得学习和借鉴的点。很多实现非常的巧妙,值得我们实践到日常的开发中。
当然了,关于这个三个组件,每过一段时间阅读其源码都会有不一样的收获,都会有一些新的思考。本次阅读理解接到这里,权当是现阶段的理解,后面如果有新的体会,有更高层次的理解,再次补充。
参考文档