本文涉及的源碼版本以下:java
ViewModel用於存儲和管理UI相關的數據,ViewModel有本身生命週期,會根據fragment,activity的生命週期銷燬。當配置發生改變時, ViewModel存儲的數據仍是存在的,不會被銷燬。(例如旋轉屏幕,旋轉屏幕一般會致使activity重建)android
ViewModel:抽象類,onCleared方法用於釋放資源bash
AndroidViewModel: 繼承了ViewModel, 沒什麼區別, 構造能夠傳入一個application網絡
ViewModelStore: ViewModel存儲器, 內部Map存儲多線程
ViewModelStoreOwner: 一個接口, ViewModelStore擁有者。 Fragment和FragmentActivity實現了接口app
Factory: 一個工廠接口,用於建立ViewModel。是ViewModelProvider的內部接口異步
NewInstanceFactory: 繼承Factory, 經過反射class.newInstance()產生一個ViewModel。因此使用這個Factory,ViewModel須要有空參構造器。ide
AndroidViewModelFactory: 繼承Factory, 也是經過反射產生一個AndroidViewModel, 並且這個AndroidViewModel構造器必須只有一個application參數, 如何反射建立失敗會調用NewInstanceFactory去建立。工具
ViewModelProvider: 是一個幫助類,構造器能夠傳入ViewModelStore和Factory, 會根據Factory產生一個ViewModel, 並存儲到ViewModelStore裏。post
ViewModel的生命週期是跟fragment, activity生命週期關聯的。只有fragment, activity銷燬時纔會調用ViewModel.onCleared() (配置改爲致使銷燬,不會調用onCleared)
ViewModel存儲在ViewModelStore, ViewModel的onCleared方法在ViewModelStore的clear方法時被調用, ViewModelStore源碼以下:
private final HashMap<String, ViewModel> mMap = new HashMap<>();
/** * Clears internal storage and notifies ViewModels that they are no longer used. */
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.onCleared();
}
mMap.clear();
}
複製代碼
下面看看Fragment, 和FragmentActivity的實現,先看Fragment的實現:
public ViewModelStore getViewModelStore() {
if (getContext() == null) {
throw new IllegalStateException("Can't access ViewModels from detached fragment");
}
// new一個ViewModelStore, 一個Fragment只有一個ViewModelStore
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
return mViewModelStore;
}
public void onDestroy() {
mCalled = true;
// Use mStateSaved instead of isStateSaved() since we're past onStop()
if (mViewModelStore != null && !mHost.mFragmentManager.mStateSaved) {
mViewModelStore.clear(); // mStateSaved用於判讀是否因爲配置改變致使Fragment重建
}
}
複製代碼
再看FragmentActivity的實現
public ViewModelStore getViewModelStore() {
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) {
mViewModelStore = new ViewModelStore();
}
return mViewModelStore;
}
protected void onDestroy() {
super.onDestroy();
....
if (mViewModelStore != null && !mRetaining) {
// mRetaining用於判讀是否因爲配置改變致使Fragment重建
mViewModelStore.clear();
}
}
複製代碼
ViewModel存儲的數據不會在配置改變時而銷燬, ViewModel是怎樣保存的呢,看前面的分析在Fragment, FragmentActivity都有一個mViewModelStore的成員變量,只要保存好這個mViewModelStore這個就能夠啦。當配置改變時,在onSaveInstanceState裏保存數據,而後在onRestoreInstanceState恢復數據,可是這兩個方法存儲數據只能放在Bundle, 只能存小量數據, 過大會拋TransactionTooLargeException異常。因此不合適,看源碼發現是利用Activity的onRetainNonConfigurationInstance()和getLastNonConfigurationInstance()。
// FragmentActivity關鍵代碼
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
// 這方法繼承自Activty, 且把方法定義成final,不讓子類實現,可是提供onRetainCustomNonConfigurationInstance方法
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
//fragments是當前activity全部fragment須要保存的數據
if (fragments == null && mViewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = mViewModelStore;
nci.fragments = fragments;
// mViewModelStore 和 fragments 就存在NonConfigurationInstances裏
return nci;
}
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
// 調用getLastNonConfigurationInstance方法獲取NonConfigurationInstances恢復數據
if (nc != null) {
mViewModelStore = nc.viewModelStore;
}
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
//nc.fragments經過mFragments.restoreAllState()恢復
}
...
}
複製代碼
這裏onRetainNonConfigurationInstance和getLastNonConfigurationInstance方法就不深刻啦,配置改變時還想保存一些自定義object數據能夠重寫onRetainCustomNonConfigurationInstance去實現。那Fragment的mViewModelStore呢,就是mFragments.retainNestedNonConfig() 和 mFragments.restoreAllState() 這兩個方法啦。 mFragments是FragmentController實例,最後是調用到FragmentManager, 而FragmentManager真正實現是FragmentManagerImpl。下面截取部分FragmentManagerImpl的關鍵代碼。
// 這個方法就Activity裏mFragments.retainNestedNonConfig()最終調用的方法
FragmentManagerNonConfig retainNonConfig() {
setRetaining(mSavedNonConfig); // 因爲篇幅的緣由, 這個方法本文不展開了
return mSavedNonConfig;
}
//來看mSavedNonConfig這個實例是在哪裏建立的,回到FragmentActivity.onSaveInstanceState方法裏發現調用mFragments.saveAllState()保存狀態,最終來到FragmentManagerImpl的saveAllState()
Parcelable saveAllState() {
mSavedNonConfig = null;
saveNonConfig();
}
void saveNonConfig() {
ArrayList<Fragment> fragments = null;
ArrayList<FragmentManagerNonConfig> childFragments = null;
ArrayList<ViewModelStore> viewModelStores = null;
if (mActive != null) {
//mActive是SparseArray<Fragment>, 表明fragment棧, 遍歷mActive,
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.valueAt(i);
if (f != null) {
...
if (viewModelStores != null) {
// 把fragment的成員變量mViewModelStore添加到list中
viewModelStores.add(f.mViewModelStore);
}
}
}
}
if (fragments == null && childFragments == null && viewModelStores == null) {
mSavedNonConfig = null;
} else {
//viewModelStores存儲到FragmentManagerNonConfig裏
mSavedNonConfig = new FragmentManagerNonConfig(fragments, childFragments,
viewModelStores);
}
}
//mFragments.restoreAllState() 最終調用FragmentManagerImpl的restoreAllState()
void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
if (state == null) return;
FragmentManagerState fms = (FragmentManagerState)state;
//fms是保存狀態時存儲在Parcelable的,如今拿出來恢復狀態
if (fms.mActive == null) return;
//這裏有不少種狀況,這裏大概分析常見的恢復過程
...
mActive = new SparseArray<>(fms.mActive.length);
//遍歷FragmentState
for (int i=0; i<fms.mActive.length; i++) {
FragmentState fs = fms.mActive[i];
if (fs != null) {
...
ViewModelStore viewModelStore = null;
if (viewModelStores != null && i < viewModelStores.size()) {
viewModelStore = viewModelStores.get(i);
}
Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig,
viewModelStore);
// 傳入viewModelStore, 調用instantiate方法從新生成Fragment
if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
mActive.put(f.mIndex, f);
}
}
}
複製代碼
LiveData是一個可觀察數據的持有者, 可是不像普通的可觀察數據, LiveData是綁定了生命週期,例如activitie, fragment的生命週期。有點抽象, 仍是先了解一下關鍵的類。
//Observer是一個接口,觀察者。當數據改變時就回調onChanged
public interface Observer<T> {
void onChanged(@Nullable T t);
}
//LiveData類是個抽象類,這裏先看看有什麼暴露出去的方法
public abstract class LiveData<T> {
//添加觀察者觀察, 傳入LifecycleOwner,用於來綁定生命週期
public void observe(LifecycleOwner owner, Observer<T> observer) //添加觀察者觀察, 可是是沒有LifecycleOwner public void observeForever(Observer<T> observer) //移除觀察者 public void removeObserver(Observer<T> observer) //移除某個LifecycleOwner裏全部的觀察者 public void removeObservers(final LifecycleOwner owner) //是否有觀察者 public boolean hasObservers() //是否有活的觀察者 public boolean hasActiveObservers() } //MutableLiveData繼承LiveData, 多開放2個方法。 public class MutableLiveData<T> extends LiveData<T> {
public void postValue(T value) //post一個數據 public void setValue(T value) //設置一個數據 //postValue和setValue的區別是:post能夠在子線程用,而setValue只能在UI線程調用 } 複製代碼
介紹完了主要的類,下面舉個例子:
// 這段代碼一般在Activity或者Fragment中, 用liveData去添加一個觀察者
// AppCompatActivity或者Fragment已經LifecycleOwner,一般傳this便可
// 當User數據有變化時,onChanged方法會被調用, 用於更新UI
liveData.observe(this, new Observer<User>() {
@Override
public void onChanged(@Nullable User user) {
//更新UI
}
});
//下面這段代碼一般在ViewModel中,這裏liveData和上面代碼的liveData是同一個
//能夠經過postValue或者setValue去改爲user數據, 有數據改變時, onChanged方法會被回調
//假如一個場景, 在ViewModel中,經過網絡請求去拿user數據,而後postValue就會去通知UI層onChanged去更新UI
//liveData大概就是這個流程
liveData = new MutableLiveData<User>()
liveData.postValue(user)// 或者setValue(user)
複製代碼
下面仍是看看LiveData源碼去了解一下原理
這裏以observe(LifecycleOwner owner, Observer observer) 和 postValue之間數據的通信爲例分析。對LifecycleOwner不熟悉的能夠看個人上一篇文章:LifecycleOwner, 下面看LiveData.observe源碼:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
//判斷當前生命週期是DESTROYED, 立馬return, 都銷燬了,添加觀察者沒意義
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//LifecycleBoundObserver繼承ObserverWrapper, LifecycleBoundObserver實現LifecycleOwner
//mObservers這是一個Map, key是observer, value是ObserverWrapper
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和ObserverWrapper片斷:
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
@Override
boolean shouldBeActive() {
//至少是STARTED狀態
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//GenericLifecycleObserver繼承自LifecycleObserver, 當生命週期改變時onStateChanged會被回調
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//生命週期處於DESTROYED時, 移除觀察者,mObserver是livedata.observe時傳進來
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
//shouldBeActive()方法實如今當前類, 調用isAtLeast(STARTED), 至少是STARTED狀態纔是true
//就是生命週期在STARTED和RESUME狀態時, 纔是true
//接着調用了父類的activeStateChanged
activeStateChanged(shouldBeActive());
}
}
private abstract class ObserverWrapper {
void activeStateChanged(boolean newActive) {
// mActive狀態相同當即返回
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
//就是生命週期在STARTED和RESUME時, mActive爲true, 其餘爲false
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
//當mActive=true時, mActiveCount會加1, 當mActive=false時, mActiveCount會減1。
//這裏爲何要加1和減1呢,結合Activity生命週期去考慮,當Activity.onCreate -> Activity.onStart -> Activity.onResume, State由CREATED->STARTED->RESUMED,這個過程當到STARTED時mActive爲true,mActiveCount加1後爲1, 接着RESUMED, mActive仍是true, 這方法第一句(newActive == mActive)條件成立直接return, mActiveCount此時仍是1。
//當Activity.onResume->Activity.onPause->Activity.onStop,State由RESUMED->STARTED->CREATED, Activity.onStop後State爲CREATED, isAtLeast(STARTED)就爲false, 此時mActive=false, mActiveCount減1,mActiveCount爲0啦。
//當Activity.onStop->Activity.onStart->Activity.onResume, State由CREATED->STARTED->RESUMED, mActive爲true,mActiveCount加1後爲1, mActiveCount此時爲1。
if (wasInactive && mActive) {
//根據上面一大段分析後,onActive會在Activity首次顯示UI調用,從後臺返回或者從另外一個Activity回退後又調用一次。(打開透明Activity不走onStop,這種狀況除外)
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
// Activity.onStop後調用
onInactive();
}
if (mActive) {
//分發數據, 跟蹤dispatchingValue方法,會到LiveData.considerNotify方法
dispatchingValue(this);
}
}
}
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
//mActive能夠知道是否處於onStop狀態, 是Stop狀態就不要分發數據
return;
}
if (!observer.shouldBeActive()) {
//shouldBeActive()再次檢查是否observer活着
//ObserverWrapper的實現類不止LifecycleBoundObserver, 這裏暫時沒看懂爲何再次檢查
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
//mVersion會在調用postValue()或者setValue()處+1
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
調用onChanged分發改變的數據
}
複製代碼
接着看postValue方法是是若是把值傳到onChanged裏:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
// 一開始看到這裏有點疑問,1. 爲何加鎖, 1. 爲何要一個NOT_SET變量(NOT_SET是一個Obj對象)
// 先帶着疑問往下看
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) { // 先往下看,和加鎖問題一塊兒解釋
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
// mPostValueRunnable運行在主線程
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) { //加鎖, 和postValue裏的鎖是同樣的
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++; // 版本號加1,保證mVersion>mLastVersion
mData = value; // 賦值給mData, 數據會分發到mObserver.onChanged
dispatchingValue(null);
//到這裏很清晰啦,如今回頭看看postValue和mPostValueRunnable裏的鎖,和NOT_SET的做用
//1. postValue方法可能會被不少條線程調用
//2. mPostValueRunnable異步運行在主線程, 主線程是串聯執行的,一次執行一個runnable
//3. 不加鎖很明顯不行, 多線程調用時, value從postValue方法賦值給mPendingData,
//在mPostValueRunnable主線程裏把mPendingData賦值給mData,
//mPendingData和mData都是指向同一個對象, mData在主線程都是指向了最新的對象。
//在主線程隊列的裏mPostValueRunnable每次運行都是拿了最新的數據,有點多餘
//4. 假如去掉NOT_SET, value從postValue方法賦值給mPendingData,
// 再到setValue的mData, mPendingData和mData都是指向同一個對象,
// 雖然加了鎖也沒用。但有了NOT_SET就不一樣啦, mPendingData地址給mData,NOT_SET地址給mPendingData,
// 在postValue方法的子線程裏新進來的value地址又賦值給mPendingData。
//5.看回postValue方法裏 if (!postTask) { return } 這個地方,
// 假如A線程調用了postValue, 把value賦值給mPendingData並釋放了鎖,
// 把A.mPostValueRunnable放到主線程的Message中,
// 但這時以前的B.mPostValueRunnable還沒運行完,運行到setValue方法,也沒有持有鎖。
// 這時B線程也調用了postValue, 這時A.mPostValueRunnable還沒運行,沒有把mPendingData=NOT_SET,
// B線程postTask就爲false了, 接着又把value賦值給mPendingData, 接着就直接return。
// 等A.mPostValueRunnable運行時, mPendingData又被B線程更新啦。
// if (!postTask) { return } 這個判斷能減小主線程不必mPostValueRunnable運行,
// 並且能更新到最新的數據。
}
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
// initiator是null , 下面是遍歷mObservers存儲ObserverWrapper通知全部觀察者
...
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
// considerNotify前面分析過了,看回LiveData.observe的過程, 最終分發數據Observer.onChanged
}
}
複製代碼
先說說使用ViewModel和LiveData時注意事項:
public class UserActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
...
findViewById(R.id.btn_logout).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mViewModel.onLogout(); // 點擊按鈕退出登陸
}
});
mViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
//ViewModelProviders是一個工具類,默認包含AndroidViewModelFactory把UserViewModel.class經過反射建立ViewModel並存儲在Activity中
mViewModel.getUserLiveData().observe(this, new Observer<User>() {
@Override
public void onChanged(@Nullable User user) {
//在觀察者中更新UI
if(user != null){
mTvName.setText(user.name);
}else {
//沒有登陸的狀態
mTvName.setText("用戶還沒登陸!!!!!");
}
}
});
mViewModel.loadUserInfo();
}
}
public class UserViewModel extends ViewModel {
//userLiveData存儲在UserViewModel
private final MutableLiveData<User> userLiveData = new MutableLiveData<User>();
public MutableLiveData<User> getUserLiveData() {
return userLiveData;
}
@Override
protected void onCleared() {
//釋放資源
}
public void loadUserInfo() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
//開啓一個線程,異步操做,建議使用線程池,這裏演示就直接new Thread
User user = new User();
user.name = "Albert";
userLiveData.postValue(user); // 通知數據觀察者
}
}).start();
}
public void onLogout() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
/開啓一個線程,異步操做
userLiveData.postValue(null); // 通知數據觀察者
}
}).start();
}
}
複製代碼
介紹完例子,下面說說優勢:
參考: