JetPack之LiveData與ViewModel
1.簡述
LiveData從字面上看是與生命周期相關(guān)的數(shù)據(jù),是一個數(shù)據(jù)的持有者揍移。谷歌官方說明是“LiveData 具有生命周期感知能力,如果觀察者(由 Observer 類表示)的生命周期處于 STARTED 或 RESUMED 狀態(tài),則 LiveData 會認(rèn)為該觀察者處于活躍狀態(tài)黍图。LiveData 只會將更新通知給活躍的觀察者。為觀察 LiveData 對象而注冊的非活躍觀察者不會收到更改通知奴烙≈唬”
2.使用
LiveData是一個抽象類,內(nèi)部沒有暴露任何公共方法切诀,它的最簡單的實現(xiàn)者是MutableLiveData揩环。使用時,通過setValue或postValue來發(fā)送數(shù)據(jù)內(nèi)容幅虑,后者可以在子線程中調(diào)用丰滑。簡單使用示例:
public class LiveDataActivity extends AppCompatActivity {
private static final String TAG = "LiveDataActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
MutableLiveData<String> liveData = new MutableLiveData<>();
liveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.e(TAG, "new data: " + s);
}
});
liveData.setValue("hello world");
}
}
輸出為:
E/LiveDataActivity: new data: hello world
上面是LiveData的最簡單的使用。事實上倒庵,Jetpack并不建議這樣使用LiveData褒墨,請確保將用于更新界面的 LiveData 對象存儲在 ViewModel 對象中,而不是將其存儲在 Activity 或 Fragment 中擎宝,原因如下:
1)避免 Activity 和 Fragment 過于龐大∮袈瑁現(xiàn)在,這些界面控制器負(fù)責(zé)顯示數(shù)據(jù)认臊,但不負(fù)責(zé)存儲數(shù)據(jù)狀態(tài)圃庭。
2)將 LiveData 實例與特定的 Activity 或 Fragment 實例分離開,并使對象在配置更改后繼續(xù)存在失晴。
也就是說剧腻,LiveData一般在ViewModel中創(chuàng)建,以減少Activity中邏輯涂屁,同時避免Activity因為橫豎屏切換導(dǎo)致的數(shù)據(jù)丟失书在。
我們將上述示例代碼修改一下,使用LiveData來完成拆又。先在項目的gradle中添加依賴(因為不同的版本中儒旬,ViewModel獲取方式有點不同):
def lifecycle_version = "2.2.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
創(chuàng)建SimpleViewModel.java:
public class SimpleViewModel extends ViewModel {
private final MutableLiveData<String> mLiveData;
private static int mCurTime = 0;
public SimpleViewModel() {
mLiveData = new MutableLiveData<>();
mCurTime ++;
mLiveData.postValue("number " + mCurTime + ", viewModel hashcode: " + hashCode());//1
}
public LiveData<String> getDataNotify(){
return mLiveData;
}
}
最后Activity中代碼變成如下:
public class LiveDataActivity extends AppCompatActivity {
private static final String TAG = "LiveDataActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
SimpleViewModel simpleViewModel = new ViewModelProvider(this)
.get(SimpleViewModel.class);
simpleViewModel.getDataNotify().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.e(TAG, "new data: " + s);
}
});
}
}
ViewModel不能使用new來創(chuàng)建,而應(yīng)該通過ViewModelProvider來創(chuàng)建帖族,原因是如果我們通過new的方式創(chuàng)建栈源,和我們不使用ViewModel+Lifecycle+LiveData的方式?jīng)]什么區(qū)別,而通過ViewModelProvider竖般,內(nèi)部會協(xié)助管理ViewModel的生命周期甚垦。
我們嘗試橫豎屏切換,按照代碼邏輯,如果LiveData重建了艰亮,那么內(nèi)部的mCurTime靜態(tài)成員應(yīng)該每次都會自增1闭翩。實際日志輸出如下:
2020-06-14 18:00:46.448 4506-4506/com.hudson.newfeaturetest E/LiveDataActivity: new data: number 1, viewModel hashcode: 202833815
2020-06-14 18:00:53.435 4506-4506/com.hudson.newfeaturetest E/LiveDataActivity: new data: number 1, viewModel hashcode: 202833815
可以發(fā)現(xiàn)兩次結(jié)果一模一樣,而且即便LiveData在ViewModel構(gòu)建時的注釋1處已經(jīng)postValue發(fā)送了數(shù)據(jù)迄埃,橫豎屏切換之后疗韵,Activity中仍然能夠獲取到之前的內(nèi)容,也就是說ViewModel似乎幫我們把數(shù)據(jù)存儲起來了侄非。這就跟ViewModel的生命周期相關(guān)了蕉汪。
3 ViewModel的生命周期
ViewModel 對象存在的時間范圍是從獲取 ViewModel 時傳遞給 ViewModelProvider 的 Lifecycle開始,ViewModel 將一直留在內(nèi)存中彩库,直到限定其存在時間范圍的 Lifecycle 永久消失:對于 Activity肤无,是在 Activity 完成時;而對于 Fragment骇钦,是在 Fragment 分離時宛渐。如下圖說明了 Activity 經(jīng)歷屏幕旋轉(zhuǎn)而后結(jié)束的過程中所處的各種生命周期狀態(tài),F(xiàn)ragment也是類似的眯搭。
通常在系統(tǒng)首次調(diào)用 Activity 對象的 onCreate() 方法時請求 ViewModel窥翩。系統(tǒng)可能會在 Activity 的整個生命周期內(nèi)多次調(diào)用 onCreate(),如在旋轉(zhuǎn)設(shè)備屏幕時鳞仙、內(nèi)存不足回收Activity后的重建時寇蚊。ViewModel 存在的時間范圍是從您首次請求 ViewModel 直到 Activity 完成并銷毀。
由于這個特性棍好,ViewModel可以用于同一個Activity內(nèi)部的多個Fragment之間來進(jìn)行數(shù)據(jù)共享仗岸。
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
public void select(Item item) {
selected.setValue(item);
}
public LiveData<Item> getSelected() {
return selected;
}
}
public class MasterFragment extends Fragment {
private SharedViewModel model;
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
public class DetailFragment extends Fragment {
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
model.getSelected().observe(getViewLifecycleOwner(), { item ->
// Update the UI.
});
}
}
這兩個 Fragment 可以使用其 Activity 范圍共享 ViewModel 來處理此類通信。
需要注意的是借笙,ViewModel存儲數(shù)據(jù)的特性并不是指持久性數(shù)據(jù)扒怖,而是指在它所處的LifecycleOwner的生命周期范圍內(nèi)的全局存儲,只要我們能拿到這個LifecycleOwner业稼,我們便可以拿到之前它創(chuàng)建的那個ViewModel盗痒。如果一個Activity通過返回鍵點擊被銷毀了,destroyed低散,那么ViewModel也將會執(zhí)行onCleared方法來清理數(shù)據(jù)俯邓,這時候你重新打開該Activity,這時會新建一個ViewModel熔号,而不是使用之前的ViewModel稽鞭,因為舊Activity已經(jīng)和原來的ViewModel解綁了递鹉。我們可以繼續(xù)使用上面的示例绩鸣,先按下back返回鍵回到主頁职烧,再重新進(jìn)入与纽,對比兩次的日志:
2020-06-14 18:40:05.918 5386-5386/com.hudson.newfeaturetest E/LiveDataActivity: new data: number 1, viewModel hashcode: 118099635
2020-06-14 18:40:36.477 5386-5386/com.hudson.newfeaturetest E/LiveDataActivity: new data: number 2, viewModel hashcode: 20262912
可以看到內(nèi)部的靜態(tài)成員自增了切端。
4.ViewModel源碼跟蹤
4.1 ViewModel的創(chuàng)建過程
從前面代碼中的ViewModelProvider開始币叹,我們可以找到ViewModel的創(chuàng)建過程
ViewModelProvider.java
...
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
...
內(nèi)部通過this()方式調(diào)用了自身的構(gòu)造方法赏壹,并傳入兩個參數(shù)百拓,一個是ViewModelStore亮瓷,另一個是Factory琴拧。
ViewModelStore從字面意思上看,它應(yīng)該是我們ViewModel的存儲器嘱支,因為Activity本身可以有多個ViewModel蚓胸,因此可以猜測內(nèi)部維護了一個ViewModel列表。在我們調(diào)用的構(gòu)造方法中除师,ViewModelStore是通過ViewModelStoreOwner來獲取的沛膳,而我們傳入的ViewModelStoreOwner實際上是Activity。果然汛聚,在我們的ComponentActivity中锹安,實現(xiàn)了ViewModelStoreOwner接口,如下所示:
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
...
public ComponentActivity() {
Lifecycle lifecycle = getLifecycle();
//noinspection ConstantConditions
if (lifecycle == null) {
throw new IllegalStateException("getLifecycle() returned null in ComponentActivity's "
+ "constructor. Please make sure you are lazily constructing your Lifecycle "
+ "in the first call to getLifecycle() rather than relying on field "
+ "initialization.");
}
// ...
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();//1
}
}
}
});
if (19 <= SDK_INT && SDK_INT <= 23) {
getLifecycle().addObserver(new ImmLeaksCleaner(this));
}
}
@NonNull
@Override
public ViewModelStore getViewModelStore() {//2
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();//3
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
...
}
內(nèi)部在注釋2處的方法中判斷ViewModelStore是否為空倚舀,為空則創(chuàng)建新對象叹哭。注釋3處的NonConfigurationInstances是Activity能在橫豎屏切換時保持生命周期而不銷毀的,從字面上看意思是與配置無關(guān)的實例痕貌。我們看下這個getLastNonConfigurationInstance方法:
/**
* Retrieve the non-configuration instance data that was previously
* returned by {@link #onRetainNonConfigurationInstance()}. This will
* be available from the initial {@link #onCreate} and
* {@link #onStart} calls to the new instance, allowing you to extract
* any useful dynamic state from the previous instance.
*
* <p>Note that the data you retrieve here should <em>only</em> be used
* as an optimization for handling configuration changes. You should always
* be able to handle getting a null pointer back, and an activity must
* still be able to restore itself to its previous state (through the
* normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this
* function returns null.
*
* <p><strong>Note:</strong> For most cases you should use the {@link Fragment} API
* {@link Fragment#setRetainInstance(boolean)} instead; this is also
* available on older platforms through the Android support libraries.
*
* @return the object previously returned by {@link #onRetainNonConfigurationInstance()}
*/
@Nullable
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
與之對應(yīng)的還有一個onRetainNonConfigurationInstance()方法风罩,這兩個方法與onSaveInstanceState()和onRestoreInstanceState()方法類似,這兩個方法可以直接使用Object來保存Activity銷毀與重建的信息舵稠。從上面的getLastNonConfigurationInstance()注釋中我們看到超升,大部分情況下,我們可以使用Fragment的setRetainInstance來設(shè)置Fragment是否跟隨Activity重建而重建哺徊。
另外在注釋1處通過getLifecycle().addObserver()來給Activity的生命周期添加了一個監(jiān)聽器室琢,并在內(nèi)部判斷Lifecycle的事件為ON_DESTROY事件且不是由于配置信息變更引起時,調(diào)用了ViewModelStore的clear方法唉工,我們跟蹤到內(nèi)部研乒,如下
ViewModelStore.java
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
可以看到上面ViewModelStore中確實維護了一個String為key,ViewModel為value的HashMap淋硝,并在clear方法中遍歷map雹熬,依次調(diào)用了ViewModel的clear()方法
ViewModel.java
...
@MainThread
final void clear() {
mCleared = true;
// Since clear() is final, this method is still called on mock objects
// and in those cases, mBagOfTags is null. It'll always be empty though
// because setTagIfAbsent and getTag are not final so we can skip
// clearing it
if (mBagOfTags != null) {
synchronized (mBagOfTags) {
for (Object value : mBagOfTags.values()) {
// see comment for the similar call in setTagIfAbsent
closeWithRuntimeException(value);//2
}
}
}
onCleared();//1
}
...
在注釋1處調(diào)用了我們之前ViewModel生命周期中的onCleared方法。因此驗證了之前生命周期中所說的谣膳,如果Activity進(jìn)入的Finished態(tài)的話竿报,ViewModel生命周期也結(jié)束了。其實clear()方法中我們發(fā)現(xiàn)继谚,ViewModel生命周期的結(jié)束烈菌,僅僅是把mCleared的標(biāo)識位設(shè)置成了true,同時注釋2處會調(diào)用Closeable對象的close方法,然后再調(diào)用了1處的onCleared()抽象方法芽世。因此如果我們在ViewModel中執(zhí)行一些異步耗時操作挚赊,內(nèi)部邏輯依然會繼續(xù)執(zhí)行,直到全部完成济瓢,因此在ViewModel中荠割,我們也應(yīng)該注意這類問題,只不過這部分的內(nèi)存泄漏并不會影響到Activity旺矾,因為ViewModelStore已經(jīng)把它從Map中移除了蔑鹦。
回到之前的ViewModelProvider構(gòu)造方法中,第二個參數(shù)是一個Factory箕宙,它的定義如下
ViewModelProvider.java
...
/**
* Implementations of {@code Factory} interface are responsible to instantiate ViewModels.
*/
public interface Factory {
/**
* Creates a new instance of the given {@code Class}.
* <p>
*
* @param modelClass a {@code Class} whose instance is requested
* @param <T> The type parameter for the ViewModel.
* @return a newly created ViewModel
*/
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();//1
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);//2
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);//3
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);//4
} else {
viewModel = (mFactory).create(modelClass);//5
}
mViewModelStore.put(key, viewModel);//6
return (T) viewModel;
}
...
可以看出嚎朽,這是一個ViewModel的構(gòu)建工廠,也就是說柬帕,我們外界可以提供一個用于構(gòu)建我們自定義ViewModel的構(gòu)建工廠哟忍,然后ViewModelProvider會通過它來構(gòu)建我們的實例。由于我們沒有傳入構(gòu)建工廠雕崩,因此ViewModelProvider會為我們創(chuàng)建默認(rèn)的構(gòu)建工廠(在部分版本中必須傳入構(gòu)建工廠)魁索。
ViewModelProvider的構(gòu)建完成了,我們接著看get方法盼铁,注釋1處獲取到了class的名字粗蔚,并在注釋2處和DEFAULT_KEY拼接起來,DEFAULT_KEY是"androidx.lifecycle.ViewModelProvider.DefaultKey"饶火,因此最終拼接起來是"androidx.lifecycle.ViewModelProvider.DefaultKey" + 名字鹏控。最終先在注釋3處獲取HashMap中是否已經(jīng)存儲了該值,有就直接獲取肤寝,沒有則通過注釋4或5處利用之前的構(gòu)建工廠創(chuàng)建当辐,然后在6處緩存起來,之后返回鲤看。至此缘揪,ViewModel分析完畢。
4.2 LiveData的數(shù)據(jù)觀察者注冊過程
前面分析中义桂,ViewModelStore內(nèi)部維護了一個String-ViewModel的HashMap集合找筝,并會在Activity銷毀時進(jìn)行一些清理工作,也知道了為什么ViewModel能夠在Activity重建了之后也能存活慷吊。上面代碼中ViewModel完成創(chuàng)建后袖裕,我們在Activity中拿到它,并通過它獲取到LiveData溉瓶,然后調(diào)用了observe方法急鳄。
LiveData.java
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {//1
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);//2
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);//3
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);//4
}
上述邏輯中谤民,1處首先判斷LifecycleOwner是否處于銷毀狀態(tài),如果是疾宏,直接忽略张足;2處創(chuàng)建一個LifecycleBoundObserver包裹了LifecycleOwner和數(shù)據(jù)監(jiān)聽的Observer,并在3處把它通過調(diào)用putIfAbsent存儲到一個Map集合中坎藐。這個地方與之前的LifecycleRegistry類似兢榨,在前面的Lifecycle分析中,LifecycleRegistry通過維護一個Map集合顺饮,保存了所有LifecycleOwner的生命周期監(jiān)聽者。這里類似凌那,LiveData內(nèi)部也維護了一個集合兼雄,保存對它這個數(shù)據(jù)變動的監(jiān)聽者列表,存儲的類型是ObserverWrapper帽蝶。
LifecycleBoundObserver.java
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
可以看到赦肋,LifecycleBoundObserver本身實現(xiàn)了LifecycleEventObserver接口,而LifecycleEventObserver接口又繼承自LifecycleObserver励稳,因此它本身也是一個LifecycleOwner(或者說Activity等)生命周期的觀察者佃乘。而且在上述代碼4處把它加入到了LifecycleOwner的觀察者集合中。
咦驹尼?本來LiveData通過observe方法添加了一個自身數(shù)據(jù)變動的觀察者到列表中趣避,而添加到列表中的這個對象實例本身又是LifecycleOwner(或者說Activity等)的觀察者。其實看上面LifecycleBoundObserver的構(gòu)造方法中新翎,外界傳入的數(shù)據(jù)變動觀察者交給了父類程帕,也就是ObserverWrapper來完成。
看后面的代碼邏輯地啰,shouldBeActive()愁拭、removeObserver()是不是有點眼熟,沒錯在Lifecycle那篇文章中亏吝,Lifecycle的使用需要我們LifecycleOwner的監(jiān)聽者去主動查詢LifecycleOwner的生命周期狀態(tài)岭埠,然后決定是否繼續(xù)進(jìn)行數(shù)據(jù)的加載(那篇文章中是定位信息的獲取)蔚鸥,如果LifecycleOwner本身處于銷毀狀態(tài)惜论,那么我們應(yīng)該停止數(shù)據(jù)的加載操作。在這里株茶,LiveData把外界傳入的數(shù)據(jù)變動觀察者移除了来涨,也就是說LiveData將不再通知這個Observer數(shù)據(jù)變動了。這也就印證了最開始的LiveData的定義启盛。
到這里蹦掐,我們發(fā)現(xiàn)技羔,原來LifecycleObserver中一些模板式的代碼邏輯,現(xiàn)在都被LiveData幫助完成了卧抗,而我們只需要關(guān)注具體的數(shù)據(jù)獲取就可以了藤滥。
4.3 LiveData的發(fā)布數(shù)據(jù)過程
LiveData通過setValue和postValue來給觀察者發(fā)布數(shù)據(jù),因此這是我們分析的入口社裆。其實postValue本質(zhì)還是調(diào)用了setValue來操作拙绊,因此只分析setValue方法。
LiveData.java
...
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");//1
mVersion++;
mData = value;
dispatchingValue(null);//2
}
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());//3
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
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 (!observer.shouldBeActive()) {//4
observer.activeStateChanged(false);//5
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);//6
}
...
上面邏輯中泳秀,1處首先判斷調(diào)用的線程是不是主線程标沪,因為setValue方法是主線程調(diào)用的方法;2處開始分發(fā)嗜傅;由于dispatchingValue傳入的是null,因此調(diào)用到3處金句,可以看到是遍歷了內(nèi)部的ObserverWrapper元素,并調(diào)用considerNotify()方法吕嘀;4處通過ObserverWrapper的shouldBeActive方法判斷LifecycleOwner的生命狀態(tài)违寞,實際上是調(diào)用了
mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
來獲取狀態(tài),如果不是活躍狀態(tài)偶房,調(diào)用5處以便LiveData來響應(yīng)不同狀態(tài)下的處理趁曼,并直接返回,這里可以看出棕洋,如果LifecycleOwner沒有處于活動狀態(tài)的話挡闰,后續(xù)邏輯不再執(zhí)行,直接返回掰盘,進(jìn)一步驗證了開頭LiveData的生命周期感知能力尿这;6處調(diào)用到實際的Observer的onChanged方法,即我們Activity中創(chuàng)建的Observer中的邏輯中庆杜。
5.總結(jié)
5.1 整體邏輯都分析完成了射众,總結(jié)一下大概類之間的關(guān)系
5.2 來檢驗一下自己
Q:LiveData是什么晃财?
A:LiveData是一個具有生命周期感知能力的數(shù)據(jù)持有者叨橱,對于數(shù)據(jù)變動的觀察者,會有選擇性地針對處在活躍狀態(tài)的觀察者發(fā)布數(shù)據(jù)断盛。
Q:LiveData本身可以直接在Activity使用罗洗,為什么需要ViewModel這中間的一層?
A:1.能夠避免Activity或Fragment中過于龐大钢猛,使得它們只負(fù)責(zé)展示數(shù)據(jù)伙菜,而存儲數(shù)據(jù)的任務(wù)交給了LiveData,而LiveData存儲在ViewModel中; 2.能夠把LiveData與Activity或Fragment實例分離命迈,并保證它們配置更改不會影響數(shù)據(jù)生命周期
Q:ViewModel是如何保證配置更改的生命周期的贩绕?
A:利用了Activity中的onRetainNonConfigurationInstance來存儲數(shù)據(jù)火的,getLastNonConfigurationInstance來獲取數(shù)據(jù)。在Activity中實現(xiàn)了ViewModelStoreOwner接口淑倾,內(nèi)部創(chuàng)建了一個ViewModelStore馏鹤,并根據(jù)前面兩個方法在配置更改時保存和獲取。ViewModelStoreOwner中維護了一個ViewModel的HashMap集合娇哆,創(chuàng)建ViewModel時首先通過ViewModelProvider會去判斷ViewModelStore中是否已經(jīng)存在該ViewModel湃累,存在則直接獲取,否則通過構(gòu)建工廠創(chuàng)建碍讨。在Activity內(nèi)部添加了LifecycleOwner的生命周期觀察者治力,并在Activity等生命周期進(jìn)入Finished狀態(tài)時,會遍歷ViewModelStoreOwner的clear方法來清理ViewModel勃黍。
Q:LiveData如何保證對不活動的觀察者不發(fā)送數(shù)據(jù)琴许?
A:首先在對LiveData添加觀察者時,會把這個觀察者包裹在一個LifecycleBoundObserver中溉躲,該類實現(xiàn)了LifecycleEventObserver接口,而LifecycleEventObserver實現(xiàn)了LifecycleObserver接口益兄。之后把包裹對象向LifecycleOwner注冊锻梳,這樣便監(jiān)聽了Activity等的生命周期,并在監(jiān)聽方法中判斷ON_DESTROY事件净捅,在內(nèi)部移除了對生命周期的監(jiān)聽疑枯;此外,在LiveData發(fā)布數(shù)據(jù)后蛔六,會遍歷LifecycleBoundObserver(代碼中時ObserverWrapper荆永,實際對象類型是LifecycleBoundObserver),并通過內(nèi)部持有的LifecycleOwner獲取當(dāng)前生命周期狀態(tài)国章,如果不屬于活躍狀態(tài)具钥,將不會繼續(xù)執(zhí)行發(fā)送數(shù)據(jù),當(dāng)它重新處于活躍狀態(tài)時液兽,下次發(fā)布數(shù)據(jù)變動骂删,還會通知到它。