Android Architecture Components是Google為開發(fā)者提供的架構(gòu)設(shè)計方案,里面包含若干內(nèi)容:
- Lifecycle
- ViewModel
- LiveData
- Room
- Paging
具體介紹和教程見官網(wǎng),暫時項目用得上是前三個,重點吹吹ViewModel和LiveData。Room是官方提供的對SQLite的抽象,知道它的存在就好,沒有找到取代greenDAO或者realm的理由。Paging支持對RecyclerView分頁加載,可以期待,但現(xiàn)在版本還是1.0.0rc,先放一邊。
現(xiàn)在最新的版本:android.arch.lifecycle:extensions:1.1.1
Lifecycle
向上找Activity的父類,在SupportActivity里實現(xiàn)了LifecycleOwner,里面只有一個方法getLifecycle。(某個版本api添加的哈,人懶沒有去查是幾)
在onCreate可以將Activity的生命周期委托給LifecycleObserver:
lifecycle.addObserver(MyLifecycleObserver())
LifecycleObserver是一個接口,我們使用@OnLifecycleEvent綁定生命周期和具體的函數(shù)。除了ON_CREATE等基本的,還添加了ON_ANY。
class MyLifecycleObserver : LifecycleObserver {
companion object {
val LIFECYCLE_TAG = TAG + "lifecycle"
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreate() {
LogUtils.d("$LIFECYCLE_TAG-onCreate")
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
LogUtils.d("$LIFECYCLE_TAG-onStart")
}
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
fun onAny() {
//LogUtils.d("$LIFECYCLE_TAG-onAny")
}
}
使用Lifecycle好處顯而易見,Activity生命周期的函數(shù)不用散落到各處,可以統(tǒng)一在一個地方處理好。
ViewModel和LiveData
ViewModel就是MVVM模式中的VM,默認(rèn)你認(rèn)識MVVM和databinding,寫個demo。

Activity里有兩個Fragment(紅色是Fragment1、藍(lán)色是Fragment2),通過“上一頁”、“下一頁”切換。有一個持久化的user對象,包括“name”和“age”兩個屬性,點擊按鈕“更新user”,變更user對象的屬性并顯示在兩個Fragment中。
功能很簡單,但是需要處理常見的Fragment間通信。假如使用MVP模式,每個Fragment對應(yīng)一個Presenter。兩個Fragment之間的通信,要不使用Activity傳遞參數(shù),要不使用RxBus之類的事件總線,ViewModel提供更簡單的方法。
首先介紹LiveData,可以包裝任意類型的對象,它有三個特點:
- 供觀察者訂閱
- 感知組件(Activity、Fragment、Service)生命周期
- 提供活躍狀態(tài),活躍的才通知觀察者
在ViewModel自定義一個init函數(shù),創(chuàng)建User對象的LiveData:
private lateinit var userData: LiveData<User>
fun init() {
val user = createUser()
this.userData = userRepository.getUser(user.userId)
}
userRepository是M層的對象,我這里使用了ROOM,它可以直接返回對象的LiveData。如果是其他持久化庫,返回的user對象可以手動setValue進(jìn)MutableLiveData。MutableLiveData是LiveData的子類,可以修改值,還有一個子類MediatorLiveData,可以觀測一個或多個LiveData的變化,用到再說了。
更新值有兩個方法,一個是postValue,一個是setValue。前者可以在任意線程,后者只能在主線程。
在Activity里獲取ViewModel:
val viewModel = ViewModelProviders.of(this).get(PersonalDetailViewModel::class.java)
在Fragment里獲取ViewModel:
val viewModel = ViewModelProviders.of(activity!!).get(PersonalDetailViewModel::class.java)
兩者非常相似,要注意of函數(shù)傳入的參數(shù),無論是Activity還是Fragment,都是傳入activity對象,這樣保證它們獲取同一個ViewModel。(Activity里有個Map保存ViewModel)
viewModel.getUserData().observe(this, Observer<User> { user ->
user?.let {
tv_name.text = user.name
tv_age.text = user.age.toString()
}
})
在Fragment2中通過observe訂閱LiveData變化,當(dāng)Fragment1修改User屬性,F(xiàn)ragment2觸發(fā)Observer的onChanged函數(shù),我們對應(yīng)修改ui顯示。只要訂閱了LiveData,任意地方都可以即時知道。
既然有訂閱觀察,為什么沒有寫對應(yīng)的解綁訂閱?這就是LiveData的第二個特點,注意到observe傳入的參數(shù)是LifecycleOwner,它是可以感知組件的生命周期。當(dāng)生命周期是DESTORY時,自動解綁訂閱,具體后面分析源碼就知道了。
也有另外一個observeForever函數(shù),不需要傳入LifecycleOwner,但是需要手動使用remove,和普通的觀察者模式一樣。
還有第三個特點,活躍狀態(tài)。這個很好理解,組件處于某些狀態(tài)時,才通知觀察者變化。
LiveData源碼分析
知其然知其所以然,順手看看ViewModel和LiveData的實現(xiàn)方式。
LiveData是典型的觀察者模式,使用自定義的SafeIterableMap保存所有觀察者。
private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
鍵值對類型<Observer<T>, ObserverWrapper>,Observer是觀察者對象,ObserverWrapper是什么東西,觀察者的包裝類?
private abstract class ObserverWrapper {
final Observer<T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
//...
}
果然ObserverWrapper包裝了Observer,增加了active和version。LifecycleBoundObserver是ObserverWrapper的抽象實現(xiàn)類,包含了生命周期LifecycleOwner。他們的聯(lián)系很清楚了,對Observer的管理疊加了生命周期,看LifecycleBoundObserver其中兩個函數(shù):
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
//...
@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());
}
//...
}
當(dāng)生命周期變?yōu)镈ESTROYED時,自動移除觀察者,實現(xiàn)上節(jié)所講感知組件生命周期。當(dāng)組件處于活躍時,觀察才是有效的,這里需要生命周期至少是STARTED。最后調(diào)用ObserverWrapper.activeStateChanged處理生命周期變化。
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
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);
}
}
onActive和onInactive是兩個空函數(shù),可以讓LiveData的子類額外處理活躍變化。處于活躍時,調(diào)用dispatchingValue通知觀察者。具體的通知過程路過,不外乎是循環(huán)所有觀察者,根據(jù)條件調(diào)用onChange函數(shù)。
最后看回LiveData的訂閱函數(shù)observe,有了上面的分析,都不用講了。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
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);
}
ViewModel源碼分析
ViewModel是一個抽象類,里面只有一個clear函數(shù),需要時可以重寫做些清理。
public abstract class ViewModel {
protected void onCleared() {
}
}
使用ViewModel的入口函數(shù)在ViewModelProviders,核心是函數(shù)of,區(qū)分入?yún)ragment和Activity兩個版本。
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) {
Application application = checkApplication(checkActivity(fragment));
if (factory == null) {
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
return new ViewModelProvider(ViewModelStores.of(fragment), factory);
}
of返回的對象是ViewModelProvider,和ViewModelProviders差了個s。
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
this.mViewModelStore = store;
}
創(chuàng)建ViewModelProvider需要兩個對象:
- ViewModelStore
- Factory
Factory
public interface Factory {
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
Factory接口,只有一個函數(shù)create,傳入class,創(chuàng)建ViewModel。AndroidViewModelFactory是它的實現(xiàn)類:
//AndroidViewModelFactory
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.getConstructor(Application.class).newInstance(mApplication);
}
//catch...
}
return super.create(modelClass);
}
通過isAssignableFrom判斷class類型是不是AndroidViewModel,是的話創(chuàng)建帶Application實例的AndroidViewModel。不是的話,創(chuàng)建工作交給父類NewInstanceFactory,對應(yīng)的create函數(shù)創(chuàng)建無參構(gòu)造函數(shù)的普通ViewModel。
//NewInstanceFactory
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.newInstance();
}
//catch...
}
ViewModelStore
private final HashMap<String, ViewModel> mMap = new HashMap<>();
ViewModelStore很簡單,里面有一個HashMap,保存key和ViewModel。很明顯它是ViewModel的緩存,可以使用get和put操作。
@NonNull
@MainThread
public static ViewModelStore of(@NonNull FragmentActivity activity) {
if (activity instanceof ViewModelStoreOwner) {
return ((ViewModelStoreOwner) activity).getViewModelStore();
}
return holderFragmentFor(activity).getViewModelStore();
}
ViewModelStore通過調(diào)用ViewModelStores.of獲取,有兩種獲取來源:
- 第一種,ViewModelStore對象保存在Activity和Fragment,它們都實現(xiàn)了ViewModelStoreOwner接口。因此,可以很輕松在Activity或Fragment得到我們需要的ViewModel對象。
- 第二種,ViewModelStoreOwner接口是某個時候加入Activity的,如果之前的沒有實現(xiàn)接口又怎樣辦?
大神們弄了個HolderFragment承載ViewModelStore:
HolderFragment holderFragmentFor(FragmentActivity activity) {
FragmentManager fm = activity.getSupportFragmentManager();
HolderFragment holder = findHolderFragment(fm);
if (holder != null) {
return holder;
}
holder = mNotCommittedActivityHolders.get(activity);
if (holder != null) {
return holder;
}
if (!mActivityCallbacksIsAdded) {
mActivityCallbacksIsAdded = true;
activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);
}
holder = createHolderFragment(fm);
mNotCommittedActivityHolders.put(activity, holder);
return holder;
}
就是這個方法createHolderFragment,動態(tài)將HolderFragment添加進(jìn)Activity,然后就可以獲取ViewModelStore了。
private static HolderFragment createHolderFragment(FragmentManager fragmentManager) {
HolderFragment holder = new HolderFragment();
fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss();
return holder;
}
Fragment里添加HolderFragment類似,用的是ChildFragmentManager。
ViewModelProvider.get()
最后一步,從ViewModelProvider獲取ViewModel的get函數(shù):
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
ViewModel存在于ViewModelStore時直接獲取,否則創(chuàng)建并加入ViewModelStore,key的構(gòu)成是固定字符串加上類的canonicalName。
總結(jié)
可以用