(不白看)LiveData 原始碼閱讀
不能白看原始碼,面試如何回答
簡單的說下 LiveData 原理?
本質上是一個觀察者模式,Activity 或 Fragment 中實現觀察者,LiveData 是被觀察者,LiveData 中儲存的資料變更的時候觸發事件。
說下 LiveData 的優缺點?
優點:
- 響應式程式設計
由於觀察者模式的特性,實現了響應式程式設計,LiveData 資料變化後自動觸發 UI 更新,
- 解耦, 對 MVP 模式的補充
沒有對比就沒有傷害:傳統的 MVP 模式在使用的時候,Presenter 中需要傳入一個 介面 作為與 View 互動的橋樑,而 LiveData 剛好可以替代了這個 介面。這樣 Presenter 中就不需要持有 View(通常是View實現介面傳到Presenter中直接使用) 物件,解耦更加徹底
應該還不算是 MVVM, 個人理解使用了 DataBinding 才算 MVVM
- 實現了生命週期的監聽, 避免記憶體洩露
缺點:
暫時沒想到
LiveData 如何實現生命週期的監聽?
這個有點複雜了,很難幾句話說清楚。
白話版本:Activity, Fragment 中有一個成員變數,這個物件在 Activity 和 Fragment 的生命週期函式中會執行一個類似lifecycleChange(event)
的函式並把當前生命週期事件作為引數傳入。然後把生命週期 Event 傳遞給 LiveData。 最後 LiveData 根據生命週期事件判斷是否要取消觀察者模式的訂閱。
專業版本:Activity, Fragment 中有一個成員變數mLifecycleRegistry
,這個物件在 Activity 和 Fragment 的生命週期函式中會執行mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.XXXX);
,然後把生命週期 Event 傳遞給 LifecycleObserver。 最後 LifecycleObserver 根據生命週期事件判斷是否要取消觀察者模式的訂閱。
Activity 或者 Fragment 哪些生命週期狀態下可以接收事件訊息?
onStart, onResume, onPause
不能接收資料的生命週期時(onStop),LiveData 中資料變化會不會生效?
可以生效,在 Activity 回到onResume
的時候會顯示 LiveData 中最新的資料。
知道setValue 和 postValue 的區別嗎?
setValue
必須在主執行緒中執行,postValue
可以在子執行緒中執行。
如何實現執行緒切換的?
在內部建立了MainHandler
,構建一個Runnable
給MainHandler
執行,實現執行緒切換。
LiveData 原始碼解析
LiveData是一個數據持有者,其本身實現了觀察者模式,支援資料監控(被觀察),並且可以感知元件的生命週期。
使用
LiveData
是一個抽象類,通常在使用LiveData
的時候我們是使用其子類MutableLiveData
。
XXViewModel.class
// 建立 LiveData private MutableLiveData<Object> mDataMutableLiveData = new MutableLiveData<>(); // LiveData 改變資料, 觸發觀察者 mDataMutableLiveData.postValue(object); // setValue 在主執行緒中執行 // postValue 可以在子執行緒中執行
XXActivity
:
//獲取 ViewModel 物件 mViewModel = ViewModelProviders.of(this).get(XXViewModel.class); //設定觀察者 mViewModel.getDataMutableLiveData().observe(this, this::dataChange); // LiveData 中資料改變的時候處罰 private void dataChange(Object s) { // data change }
基本概念
LiveData 使用了觀察者模式。
-
被觀察者:
LiveData
-
觀察者,需要實現:
LifecycleOwner
介面,Activity, Fragment
都實現了LifecycleOwner
介面,所以在使用的時候我們通常使用Activity, Fragment
作為觀察者。
觀察者唯一的作用是提供:Lifecycle
物件。Lifecycle
是抽象類,實際返回的是LifecycleRegistry
物件。
LifecycleOwner.class
:
public interface LifecycleOwner { @NonNull Lifecycle getLifecycle(); }
Activity 和 Fragment 中都有成員變數mLifecycleRegistry
,並在getLifecycle
函式中返回該物件。
private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this); @Override public Lifecycle getLifecycle() { return mLifecycleRegistry; }
被觀察者新增觀察者過程
呼叫 LiveData#observer 函式
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
android.arch.lifecycle.Observer
是一個介面,裡面只有一個函式onChanged
作為被觀察者資料改變後觸發的回撥函式。
新增觀察者過程實際上是把Observer
傳遞給LiveData
物件 和LifecycleRegistry
物件。
LiveData 中儲存 observer:
private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers = new SafeIterableMap<>(); Map: observer: new LifecycleBoundObserver(owner, observer)
LifecycleRegistry 中儲存 observer:
private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap = new FastSafeIterableMap<>(); Map: LifecycleBoundObserver(owner, observer): ObserverWithState(observer, initialState)
LifecycleBoundObserver
物件作為生命週期狀態變化後呼叫函式存在
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver 生命週期變化後觸發: public void onStateChanged(LifecycleOwner source, Lifecycle.Event event)
到此關鍵物件:
- LiveData: 作為資料入口,維護觀察者和被觀察者的關係
- Observer:資料改變後最終觸發的函式,回撥介面,呼叫端實現
- LifecycleOwner: Activity, Fragment 提供 Lifecycle
- Lifecycle, LifecycleRegistry
- LifecycleObserver,GenericLifecycleObserver, LifecycleBoundObserver: 封裝了 Observer, LifecycleOwner 物件
Activity 和 Fragment 的生命週期是如何和 LiveData 產生關聯的?
LiveData 和 生命週期的關係基本操作:
生命週期正常的時候, addObserver 註冊觀察者;生命週期結束的時候 removeObserver 取消觀察者
上面新增訂閱和取消訂閱都是內部自動執行的,不需要使用者去手動觸發。
上面提到 Activity,Fragment 都實現了LifecycleOwner
介面,成員變數中有mLifecycleRegistry
物件。
在 Activty, Fragment 生命週期函式中呼叫下面函式將生命週期事件傳遞出來:
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.XXXX);
mLifecycleRegistry
觸發生命週期改變函式後,呼叫下面函式(中間省略了部分步驟)
mLifecycleObserver.onStateChanged(owner, event); LifecycleBoundObserver 就是這裡的 mLifecycleObserver //根據事件判斷是否要解除訂閱
setValue 與 postValue
setValue
必須在主執行緒中執行,postValue
可以在子執行緒中執行,
如何實現的執行緒切換?
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
ArchTaskExecutor 使用了代理模式, 實際函式執行類是 DefaultTaskExecutor
TaskExecutor 介面 |- ArchTaskExecutor 實現 |- DefaultTaskExecutor 實現
Runnable 最終執行位置:
@Override public void postToMainThread(Runnable runnable) { if (mMainHandler == null) { synchronized (mLock) { if (mMainHandler == null) { mMainHandler = new Handler(Looper.getMainLooper()); } } } //noinspection ConstantConditions mMainHandler.post(runnable); }
執行緒切換通過 Handler 實現
MainHandler 建立方式:
mMainHandler = new Handler(Looper.getMainLooper());
判斷是否是 MainThread:
Looper.getMainLooper().getThread() == Thread.currentThread();