Android Architecture Components

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。

photo

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é)

可以用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容