媳婦看了都說好!Android JetPack組件原理之Lifecycle、LiveData、ViewModel與源碼分析技巧

前言

Lifecycle、LiveData和ViewModel作爲AAC架構的核心,常常被用在Android業務架構中。在京東商城Android應用中,爲了事件傳遞等個性化需求,比如ViewModel間通信、ViewModel訪問Activity等等,以及爲了架構的擴展性,我們封裝了BaseLiveData和BaseViewModel等基礎組件,也對Activity、Fragement和ViewHolder進行了封裝,以JDLifecycleBaseActivity、LifecycleBaseFragment和LifecycleBaseViewHolder等組件強化了View層功能,構建出了各業務線統一規範架構的基石。

紙上說來終覺淺,時間比較充裕的小夥伴建議去B站觀看第三方庫系列視頻講解:Android第三方開源庫系列
Jetpack組件全家桶視頻講解:Android第三方開源庫系列—Jetpack全家桶(已完結)

在開發過程中,我們有時還會對它們的原理細節有些疑惑,比如會有Lifecycle會不會對性能造成影響、LiveData爲什麼是粘性事件的、ViewModel的生命週期是什麼樣的等等問題,這些問題或多或少會對我們的日常開發和協作造成影響,所以對這些組件的源碼分析就變得很有必要,而掌握一些分析方法更能提高效率。本文就以Lifecycle、LiveData和ViewModel三大組件的源碼分析爲例,探討一下分析方法和技巧,整體目錄如下圖所示,希望能給大家帶來收穫。

源碼下載

官方地址: https://android.googlesource.com/platform/frameworks/support/或Github: https://github.com/androidx/androidx,以上都列出了比較詳細的下載步驟和編譯方法,按步驟操作一般沒多大問題,如果已經安裝過repo工具,可以跳過第一步

1. 安裝repo

mkdir ~/bin

PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

2. 配置git中的姓名和郵箱,已配置可忽略

git config --global user.name "Your Name"

git config --global user.email "[email protected]"pet__string">"[email protected]"

3. 創建一個文件夾存放要下載的源碼

mkdir androidx-master-dev
cd androidx-master-dev

4. 使用repo命令下載源碼倉庫

repo init -u https://android.googlesource.com/platform/manifest -b androidx-master-dev
repo sync -j8 -c

5. 使用命令以Android Studio打開源碼庫

cd androidx-master-dev/frameworks/support/
./studiow

第一次打開可能會自動下載一個最新的Android Studio,稍等一會兒,就可以看到熟悉的界面了。

如圖,Lifecycle、LiveData和ViewModel三大組件的代碼都在lifecycle包下。

組件介紹

爲了對分析工作有個感性認識,先過一下各個組件的作用和簡單用法。

Lifecycle

Lifecycle可以方便我們處理Activity和Fragment的生命週期,可以將一些邏輯更加內聚和解耦,比如把資源的釋放操作從Activity的回調代碼中解耦出來,放到資源管理類中自動進行。該組件是後兩個組件的基石,理解它的原理也有助於我們理解LiveData是如何保證不會造成內存泄漏的。

下面是一個簡單的使用示例,在自定義LifecycleObserver的實現接口上,用註解的方式聲明與生命週期相關聯的方法。最後通過lifecycleOwner的getLifecycle()接口拿到Lifecycle管理類,並將定義LifecycleObserver的實現接口註冊進去。LifecycleOwner通常是一個Activity或Fragment的實例。

MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}

lifecycleOwner.getLifecycle().addObserver(new MyObserver());

LiveData

LiveData是一個數據持有組件,主要用來通知數據觀察者數據發生了更新,它通過與LifecycleOwner組件綁定,實現可以只在頁面活躍狀態下發起通知,並在頁面銷燬時自動取消訂閱,防止內存泄漏。

下面的簡單示例中,直接創建了一個MutableLiveData對象,他持有String類型的數據,通過它的observe()方法,將LifecycleOwner和監聽者傳入,實現感知生命週期並觀察數據的功能。

MutableLiveData<String> liveString = new MutableLiveData<>();
liveString.observe(mOwner, new Observer<String>() {
    @Override
    public void onChanged(@Nullable final String s) {
        Log.d(TAG, "onChanged() called with: s = [" + s + "]");
    }
});

liveString.setValue("LiveData使用案例");

ViewModel

ViewModel是MVVM中的VM,被設計用來管理View依賴的數據,通常是持有LiveData和相關的處理邏輯。ViewModel管理的數據有一個特點,就是不會隨着頁面配置改變而銷燬,但在頁面銷燬時則會正常跟着銷燬。

下面的例子中,自定義了一個ViewModel,管理users這組數據,並且封裝了加載users的處理邏輯。而View只需要監聽users,在回調中根據users處理界面就好,這樣就做到了界面和數據的分離。

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

組件關係

在實際的MVVM場景中,最常使用的是ViewModel和LiveData的API,比較通用的方式是ViewModel持有一個或多個LiveData,也就是需要我們開發者設計出這兩個組件的聚合關係。而Lifecycle組件,則是在調用LiveData的addOberver()方法時用到的,這個方法需要傳入一個LifecycleOwner對象,LifecycleOwner作爲一個接口,是Lifecycle組件的重要組成部分。

通過分析組件的源碼,可以從設計角度發現,Lifecycle組件的能力是LiveData和ViewModel實現的根本,LiveData的頁面活躍狀態下才發起通知、頁面銷燬時自動取消訂閱,以及ViewModel銷燬所管理的數據的特性,都是通過直接使用Lifecycle實現的,可以說Lifecycle是LiveData和ViewModel的重要組成部分。

源碼分析方法

01自底向上

該方法是從使用細節出發,提出問題,再進入源碼中探究答案,最後彙總出組件關係圖,獲得上層視角。在這裏以自下向上的方法,分析一下LifeCycle的源碼。

提出問題

首先,還是看這個使用示例:

MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}

lifecycleOwner.getLifecycle().addObserver(new MyObserver());

針對該示例所實現的作用,可以從輸入、處理和輸出這三個軟件過程角度提出問題:1、Activity/Fragment的生命週期如何轉化爲不同類型的Lifecycle.Event?2、Lifecycle.Event經過哪些處理?3、如何分發到特定的LifecycleObserver實現?

探究答案

Activity/Fragment的生命週期如何轉化爲不同類型的Lifecycle.Event

先來看看第一個問題怎麼在源碼中找到答案,不過在這以前,不妨先簡單猜測一下,最直接的想法是:直接在生命週期回調方法中創建對應類型的Event。在接下來的分析中,便可以着重於是不是這麼實現的,如果更復雜,那麼還有哪些是需要被特別考慮到的。

ComponentActiivty相關代碼

public class ComponentActivity extends Activity implements LifecycleOwner, Component {

    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
    }

    @CallSuper
    protected void onSaveInstanceState(Bundle outState) {
        Lifecycle lifecycle = this.getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry)lifecycle).setCurrentState(State.CREATED);
        }

        super.onSaveInstanceState(outState);
    }

    public Lifecycle getLifecycle() {
        return this.mLifecycleRegistry;
    }
}

從ComponentActiivty這個類中,可以看到它實現了LifecycleOwner接口,該類的子類也就有了提供Lifecycle的能力,除了LifecycleOwner的getLifecycle接口的實現,另外比較重要的就是ReportFragment.injectIfNeededIn(this)這條語句,以及它持有了一個Lifecycle的主要實現類LifecycleRegistry的示例。

ReportFragment的主要實現

public class ReportFragment extends Fragment {

    private static final String REPORT_FRAGMENT_TAG = "android.arch.lifecycle"
            + ".LifecycleDispatcher.report_fragment_tag";

    public static void injectIfNeededIn(Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
            // On API 29+, we can register for the correct Lifecycle callbacks directly
            activity.registerActivityLifecycleCallbacks(
                    new LifecycleCallbacks());
        }
        // Prior to API 29 and to maintain compatibility with older versions of
        // ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and
        // need to support activities that don't extend from FragmentActivity from support lib),
        // use a framework fragment to get the correct timing of Lifecycle events
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            // Hopefully, we are the first to make a transaction.
            manager.executePendingTransactions();
        }
    }
    //...

    @Override
    public void onStart() {
        super.onStart();
        dispatchStart(mProcessListener);
        dispatch(Lifecycle.Event.ON_START);
    }

    private void dispatch(@NonNull Lifecycle.Event event) {
        if (Build.VERSION.SDK_INT < 29) {
            // Only dispatch events from ReportFragment on API levels prior
            // to API 29\. On API 29+, this is handled by the ActivityLifecycleCallbacks
            // added in ReportFragment.injectIfNeededIn
            dispatch(getActivity(), event);
        }
    }

     static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }

        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }
   //...
}

靜態方法injectIfNeededIn的主要作用就是爲Activity提供Lifecycle能力,這裏分成了兩種情況,在Android 10及以上,Activity的源碼修改成自己可以註冊進LifecycleCallbacks監聽器。而爲了兼容舊版本,則需要Fragment的生命週期回調中進行分發,這也就是與最初推測相比特殊的地方,可以更加留意。不過這兩種情況都是根據生命週期創建了Event枚舉型,並最終都經過靜態方法dispatch,調用了Lifecyce的handleLifecycleEvent方法。

Lifecycle.Event經過哪些處理

LifecycRegistry

public class LifecycleRegistry extends Lifecycle {
   /**
    * Custom list that keeps observers and can handle removals / additions during traversal.
    *
    * Invariant: at any moment of time for observer1 & observer2:
    * if addition_order(observer1) < addition_order(observer2), then
    * state(observer1) >= state(observer2),
    */
    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap = new FastSafeIterableMap<>();
    private State mState;
    private final WeakReference<LifecycleOwner> mLifecycleOwner;

    public LifecycleRegistry(@NonNull LifecycleOwner provider) {
        mLifecycleOwner = new WeakReference<>(provider);
        mState = INITIALIZED;
    }

    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }

    private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        mState = next;
        ......
        sync();
        ......
    }
    ...
}

跟着源碼可以定位到Lifecycle的實現類LifecycRegistry中,它主要是封裝了對Lifecycle.Event的操作,包括了Lifecycle.Event與Lifecycle.State的同步,以及Lifecycle.State變化後通知觀察者。

先來看handleLifecycleEnvent的實現,通過傳進來的event獲取一個state枚舉值,具體的實現代碼如下:

static State getStateAfter(Event event) {
    switch(event) {
        case ON_CREATE:
        case ON_STOP:
            return State.CREATED;
        case ON_START:
        case ON_PAUSE:
            return State.STARTED;
        case ON_RESUME:
            return State.RESUMED;
        case ON_DESTROY:
            return State.DESTROYED;
        case ON_ANY:
        default:
            throw new IllegalArgumentException("Unexpected event value " + event);
    }
}

官網中有一張圖用來解釋Event和State的對應關係

getStateAfter()方法既是獲取Event事件之後的狀態,可以從圖中的箭頭方向可知具體的狀態值,比如ON_START和ON_PAUSE的箭頭都指向了STARTED狀態,也就是這倆個事件後Lifecycle處於STARTED狀態。

回到handleLifecycleEvent()方法,獲取新狀態後,就調用了moveToState()方法,該方法主要是判斷新狀態與當前狀態相比是否發生改變,如果已改變,則調用sync()同步方法繼續處理。

在進一步跟蹤方法調用前,不妨先看看LifecycleRegistry有哪些屬性,除了上面提到的mState來表示當前Lifecycle的狀態外,還有一個比較特殊和重要的屬性是mObserverMap。

/**
 * Custom list that keeps observers and can handle removals / additions during traversal.
 *
 * Invariant: at any moment of time for observer1 & observer2:
 * if addition_order(observer1) < addition_order(observer2), then
 * state(observer1) >= state(observer2),
 */
private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap = new FastSafeIterableMap<>();

該屬性可看作是一個自定義的Map,是一個可遍歷的集合,也就是說其中的元素是有序的,封裝了監聽者LifecycleObserver和監聽者的封裝ObserverWithState之間的映射關係,根據註釋可以知道,在遍歷操作其中的監聽者時,會保證其中監聽者的狀態是從大到小排序的。

監聽者的封裝ObserverWithState則是維護了每一個監聽者和其狀態,該狀態主要是爲了給調用事件分發前的判斷,另外,在分發Event事件後會同步更新自己的狀態。

static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;

    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        mState = initialState;
    }

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}

接下來繼續跟蹤方法調用,來看看sync()做了哪些處理。

private void sync() {
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    if (lifecycleOwner == null) {
        throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                                        + "garbage collected. It is too late to change lifecycle state.");
    }
    while (!isSynced()) {
        mNewEventOccurred = false;
        // no need to check eldest for nullability, because isSynced does it for us.
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            backwardPass(lifecycleOwner);
        }
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if (!mNewEventOccurred && newest != null
            && mState.compareTo(newest.getValue().mState) > 0) {
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}

該方法通過比較當前狀態和mObserverMap元素的枚舉值來確定是否分發事件,由於mObserverMap裏元素是按狀態的大到小排序的,所以這裏只需要拿第一位和最後一位元素的狀態與當前狀態比較,就可以判斷是否需要分發事件,以及是分發降級事件,還是分發升級事件。再具體一點說,如果mObserverMap裏最大狀態比當前狀態大,那就需要調用backwardPass(),遍歷mObserverMap,同步其中每一個observer狀態的同時,分發降級事件,反之,如果mObserverMap裏最小狀態比當前狀態小,就調用forwardPass()分發升級事件。

private void backwardPass(LifecycleOwner lifecycleOwner) {
    Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
        mObserverMap.descendingIterator();
    while (descendingIterator.hasNext() && !mNewEventOccurred) {
        Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
        ObserverWithState observer = entry.getValue();
        while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                && mObserverMap.contains(entry.getKey()))) {
            Event event = downEvent(observer.mState);
            pushParentState(getStateAfter(event));
            observer.dispatchEvent(lifecycleOwner, event);
            popParentState();
        }
    }
} 

private void forwardPass(LifecycleOwner lifecycleOwner) {
     Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
         mObserverMap.iteratorWithAdditions();
     while (ascendingIterator.hasNext() && !mNewEventOccurred) {
         Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
         ObserverWithState observer = entry.getValue();
         while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                 && mObserverMap.contains(entry.getKey()))) {
             pushParentState(observer.mState);
             observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
             popParentState();
         }
     }
 }

backwardPass()和forwardPass()類似,分別是以降序和升序的方式遍歷mObserverMap中的observer,再以內部循環通過downEvent()和upEvent()獲取下一步的Event事件,並通過observer.dispatchEvent()分發事件和同步狀態。直到mObserverMap中的每一個observer的狀態都與當前狀態一致爲止。

private static Event downEvent(State state) {
     switch (state) {
         case INITIALIZED:
             throw new IllegalArgumentException();
         case CREATED:
             return ON_DESTROY;
         case STARTED:
             return ON_STOP;
         case RESUMED:
             return ON_PAUSE;
         case DESTROYED:
             throw new IllegalArgumentException();
     }
     throw new IllegalArgumentException("Unexpected state value " + state);
 }

private static Event upEvent(State state) {
    switch (state) {
        case INITIALIZED:
        case DESTROYED:
            return ON_CREATE;
        case CREATED:
            return ON_START;
        case STARTED:
            return ON_RESUME;
        case RESUMED:
            throw new IllegalArgumentException();
    }
    throw new IllegalArgumentException("Unexpected state value " + state);
}

downEvent()和upEvent()的實現同樣可以從官網給的Event與State的關係圖中找到對應關係。下面再放一下這張圖。

downEvent()降級事件就是狀態向後箭頭對應的事件,而upEvent()升級事件則是狀態向前箭頭對應的事件。比如說CREATED的升級事件是ON_START,通過ON_START,CREATED升級爲STARTED。CREATED的降級事件是ON_DESTROY,通過ON_DESTROY,CREATED降級爲DESTROY。

方法調用流轉到這裏,已經分析完Event從創建到分發的處理過程,接下來就來解決剛開始提出的第三個問題。

如何分發到特定的LifecycleObserver實現

通過ObserverWithState,可以發現dispatchEvent()方法是直接調用mLifecycleObserver接口的onStateChanged()進行的事件分發,那麼mLifecycleObserver的具體實現是怎樣的呢?通過 mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer)可以知道靜態方法Lifecycling.lifecycleEventObserver()對傳入的監聽者進行了處理,接下來就來看看該方法是怎麼實現的。

static LifecycleEventObserver lifecycleEventObserver(Object object) {
    boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
    boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
    if (isLifecycleEventObserver && isFullLifecycleObserver) {
        return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
                                                (LifecycleEventObserver) object);
    }
    if (isFullLifecycleObserver) {
        return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
    }

    if (isLifecycleEventObserver) {
        return (LifecycleEventObserver) object;
    }

    final Class<?> klass = object.getClass();
    int type = getObserverConstructorType(klass);
    if (type == GENERATED_CALLBACK) {
        List<Constructor<? extends GeneratedAdapter>> constructors =
            sClassToAdapters.get(klass);
        if (constructors.size() == 1) {
            GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                constructors.get(0), object);
            return new SingleGeneratedAdapterObserver(generatedAdapter);
        }
        GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
        for (int i = 0; i < constructors.size(); i++) {
            adapters[i] = createGeneratedAdapter(constructors.get(i), object);
        }
        return new CompositeGeneratedAdaptersObserver(adapters);
    }
    return new ReflectiveGenericLifecycleObserver(object);
}

該方法主要將傳入的監聽者進行封裝,方便生命週期事件的轉發,這個封裝分成了三種方式,每一種可看作是後面的優化,第一種性能最高,傳入的監聽者直接是接口的實例,但由於生命週期回調方法比較多,接口的實例默認是實現了所有方法,而大部分情況並不需要監聽所有生命週期,所以這一部分在java8接口默認方法的支持下比較好用。第二種是判斷傳入的監聽者是不是已用註解解析器處理,生成了對應的封裝類,如果項目中配置了註解解析,那麼在編譯過程中就會生成相應的類型,相對應於運行時反射解析方法的方式,編譯時通過註解生成類型在代碼執行時性能更高。第三種就是運行時反射解析的處理了,限於篇幅,這裏就只追蹤一下第三種方式的處理過程。

直接定位到ReflectiveGenericLifecycleObserver類。

class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver {
    private final Object mWrapped;
    private final CallbackInfo mInfo;

    ReflectiveGenericLifecycleObserver(Object wrapped) {
        mWrapped = wrapped;
        mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
    }

    @Override
    public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) {
        mInfo.invokeCallbacks(source, event, mWrapped);
    }
}

該類的實現很簡單,在創建實例時,使用getInfo()方法,通過傳入監聽者的class,構造出CallbackInfo實例。在接受到生命週期回調後,方法流轉到CallbackInfo實例的invokeCallbacks()方法上。

CallbackInfo getInfo(Class<?> klass) {
    CallbackInfo existing = mCallbackMap.get(klass);
    if (existing != null) {
        return existing;
    }
    existing = createInfo(klass, null);
    return existing;
}

getInfo()查看是否已有緩存,如果沒有,就調用createInfo()方法解析class對象。

private CallbackInfo createInfo(Class<?> klass, @Nullable Method[] declaredMethods) {
    Map<MethodReference, Lifecycle.Event> handlerToEvent = new HashMap<>();
    ...
    Method[] methods = declaredMethods != null ? declaredMethods : getDeclaredMethods(klass);
    for (Method method : methods) {
        OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
        if (annotation == null) {
            continue;
        }
        hasLifecycleMethods = true;
        Class<?>[] params = method.getParameterTypes();
        int callType = CALL_TYPE_NO_ARG;
        if (params.length > 0) {
            callType = CALL_TYPE_PROVIDER;
            if (!params[0].isAssignableFrom(LifecycleOwner.class)) {
                throw new IllegalArgumentException(
                    "invalid parameter type. Must be one and instanceof LifecycleOwner");
            }
        }
        Lifecycle.Event event = annotation.value();

        if (params.length > 1) {
            callType = CALL_TYPE_PROVIDER_WITH_EVENT;
            if (!params[1].isAssignableFrom(Lifecycle.Event.class)) {
                throw new IllegalArgumentException(
                    "invalid parameter type. second arg must be an event");
            }
            if (event != Lifecycle.Event.ON_ANY) {
                throw new IllegalArgumentException(
                    "Second arg is supported only for ON_ANY value");
            }
        }
        if (params.length > 2) {
            throw new IllegalArgumentException("cannot have more than 2 params");
        }
        MethodReference methodReference = new MethodReference(callType, method);
        verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
    }
    CallbackInfo info = new CallbackInfo(handlerToEvent);
    mCallbackMap.put(klass, info);
    mHasLifecycleMethods.put(klass, hasLifecycleMethods);
    return info;
}

createInfo()方法主要是對類中的方法的遍歷處理,這裏只接受三種類型的方法,使用callType區分,第一種CALL_TYPE_NO_ARG是沒有參數的方法,第二種CALL_TYPE_PROVIDER是一個參數的方法,參數類型爲LifecycleOwner本身,第三種CALL_TYPE_PROVIDER_WITH_EVENT是二個參數的方法,第一個參數類型同CALL_TYPE_PROVIDER一樣,第二個參數則是ON_ANY枚舉值的Event。

每次遍歷會將方法用MethodReference封裝起來,並使用hanlderToEvent建立MethodReference與event的映射關係,注意這時候一個方法只能有一種Event事件類型相對應,最後以hanlderToEvent這個map創建CallbackInfo對象。

static class CallbackInfo {
    final Map<Lifecycle.Event, List<MethodReference>> mEventToHandlers;
    final Map<MethodReference, Lifecycle.Event> mHandlerToEvent;

    CallbackInfo(Map<MethodReference, Lifecycle.Event> handlerToEvent) {
        mHandlerToEvent = handlerToEvent;
        mEventToHandlers = new HashMap<>();
        for (Map.Entry<MethodReference, Lifecycle.Event> entry : handlerToEvent.entrySet()) {
            Lifecycle.Event event = entry.getValue();
            List<MethodReference> methodReferences = mEventToHandlers.get(event);
            if (methodReferences == null) {
                methodReferences = new ArrayList<>();
                mEventToHandlers.put(event, methodReferences);
            }
            methodReferences.add(entry.getKey());
        }
    }

    @SuppressWarnings("ConstantConditions")
    void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) {
        invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target);
        invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY), source, event,
                              target);
    }

    private static void invokeMethodsForEvent(List<MethodReference> handlers,
                                              LifecycleOwner source, Lifecycle.Event event, Object mWrapped) {
        if (handlers != null) {
            for (int i = handlers.size() - 1; i >= 0; i--) {
                handlers.get(i).invokeCallback(source, event, mWrapped);
            }
        }
    }
}

CallbakcInfo在創建時,會解析hanlderToEvent,把一個MethodReference對應一個event的關係,轉化爲一個event對應多個MethodReference,並存入到mEventToHandlers中。這樣在被調用invokeCallbacks()方法時,只需要從mEventToHandlers中取出對應的MethodReference,就可以回調監聽者了。

static final class MethodReference {
    final int mCallType;
    final Method mMethod;

    MethodReference(int callType, Method method) {
        mCallType = callType;
        mMethod = method;
        mMethod.setAccessible(true);
    }

    void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) {
        //noinspection TryWithIdenticalCatches
        try {
            switch (mCallType) {
                case CALL_TYPE_NO_ARG:
                    mMethod.invoke(target);
                    break;
                case CALL_TYPE_PROVIDER:
                    mMethod.invoke(target, source);
                    break;
                case CALL_TYPE_PROVIDER_WITH_EVENT:
                    mMethod.invoke(target, source, event);
                    break;
            }
        } catch (InvocationTargetException e) {
            throw new RuntimeException("Failed to call observer method", e.getCause());
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    ...
}

invokeCallback()就是根據callType對mMethod進行反射調用,最終執行到Lifecycling.lifecycleEventObserver()傳入的監聽器的方法實現中。

到此,Lifecycle的基本流程已經分析完了。接下來,可以使用類圖對Lifecycle的處理流程做下總結。

類關係圖

該圖使用simpleUML工具生成

用最初的使用代碼來解釋一下這個類圖。

lifecycleOwner.getLifecycle().addObserver(new MyObserver());

首先,通過LifecycleOwner拿到Lifecycle示例,LifecycleOwner是提供獲取Lifecycle實例的接口,一般ComponentActvitiy和Fragment會實現這個接口,這個新舊代碼有些差別,使用時需要區分。

然後,Lifecycle實例一般具體類型是LifecycleRegistry,它裏面使用State管理當前的生命週期狀態,同時每個監聽者LifecycleObserver也都有一個State,表示監聽者當前的狀態,生命週期事件Event發生後,會在LifecycleRegistry內與State發生互相轉化,再使用這個轉化後最新的State,與所有監聽者的State比較,到達完整無誤地通知監聽者生命週期事件的目的。

最後,監聽者註冊進Lifecycle時,一般情況下會使用ReflectiveGenericLifecycleObserver封裝,ReflectiveGenericLifecycleObserver本身也是LifecycleObserver接口的實現,它還封裝了從傳入監聽者類中解析的CallbackInfo,在被通知生命週期事件時,會使用CallbackInfo反射調用到用戶聲明的接口方法實現上。

自底向上方法總結

自底向上的方式分析源碼主要在於分析前問題的提出,上面應用了軟件過程中的輸入、處理和輸出這三個角度提出問題,算是比較通用的一種方式。問題提出後,便可以以解決問題爲目的分析源碼,不至於在茫茫源碼中迷失了方向。解決完問題,緊接着把源碼的主要流程梳理一遍,做出總結,即可以加深對原理的理解。

02自頂向下

自頂向下分析源碼與自底向上在思路上正好相反,需要先繪製出組件的類關係圖,然後抽出主要方法,進一步解析方法,從而掌握實現細節,它適合於在對源碼組件有一個整體上的瞭解前提下進行,可以深刻掌握組件的原理特性。接下來就使用該方法總結出LiveData的特性。

首先還是以一個示例開始:

MutableLiveData<String> liveString = new MutableLiveData<>();
liveString.observe(mOwner, new Observer<String>() {
    @Override
    public void onChanged(@Nullable final String s) {
        Log.d(TAG, "onChanged() called with: s = [" + s + "]");
    }
});

liveString.setValue("LiveData使用案例");    

該例子包含了使用LIveData的基本三部分:定義、註冊監聽者、更新數據。可以同樣以軟件過程的輸入、處理和輸出三個角度爲切入點進行分析。處了定義外,監聽者相關的操作可以看作是輸出,比如註冊、回調、註銷。更新數據則可以看作是輸入,而處理則是在LiveData的內部完成。

類關係圖

LiveData的類關係圖並不複雜,它只有5個類,除了示例中已經出現的有Observer和MutableLiveData,而主要類LiveData則包含和處理的主要邏輯,LiveData的內部類ObserverWrapper和LifecycleBoundObserver則提供了封裝Observer和Lifecycle生命週期管理的能力。這裏也可以看出LiveData依賴Livecycle的關係。

可以從類圖中抽出需要分析的方法,回到輸入、處理和輸出的角度,對應的就是數據更新、數據流轉和監聽者處理三類方法。

輸入-數據更新:postValue()、setValue()、onStateChanged()

處理-數據流轉:activeStateChanged()、dispatchingValue()、considerNotify()

輸出-監聽者處理:observe()、removeObserver()、onChanged()

接下來,可以使用在源碼方法間快速跳轉的方式,手動定位並列出相應處理鏈。

從該圖中可以看出觸發數據通知的兩個處理鏈:

1. 註冊監聽者後,可以接收到Lifecycle事件,這時候可能會移除監聽者,也可能觸發了數據通知

2. 手動postValue或setValue觸發數據通知

接下來,便以這兩個任務鏈的順序,對每個方法進行分析。

observer()註冊監聽者

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    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);
}

該方法就是把Lifecycle持有對象LifecycleOwner和一個監聽者observer傳進來,實現這個監聽者在這個生命週期作用域下對LiveData的數據進行監聽。這裏主要的處理是對observer使用Lifecycle的監聽者LifecycleBoundObserver進行了封裝,並存入管理所有監聽者的mObservers中。這裏除了過濾避免重複外,還對監聽者對應的LifecycleOwner進行了判斷,防止一個監聽者處於多個Lifecycle作用域進而導致混亂的情況發生。

LifecycleBoundObserver的onStateChanged()

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
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

onStateChanged()的邏輯是LifecycleBoundObserver中對接口LifecycleEventObserver的實現,通過對Lifecycle組件的瞭解,可以知道在LifecycleOwner的生命週期發生改變時,onStateChanged()方法就會被調用到。這裏判斷如果LifecycleOwner銷燬了,那麼就移除這個監聽者,達到防止內存泄漏的目的,其它情況則會以shouldBeActivie()爲值調用activeStateChanged()方法。shouldBeActivie()判斷LifecycleOwner的狀態是否處於STARTED之後,也就是是否顯示在屏幕中,這裏表明了LiveData的另一個特性,默認情況下,顯示在屏幕中的頁面中的監聽者纔會收到數據更新的通知。

ObserverWrapper的activeStateChanged()

private abstract class ObserverWrapper {
    final Observer<? super T> mObserver;
    boolean mActive;
    int mLastVersion = START_VERSION;

    ObserverWrapper(Observer<? super T> observer) {
        mObserver = observer;
    }

    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver() {
    }

    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);
        }
    }
}

activeStateChanged()方法是在LifecycleBoundObserver的父類ObserverWrapper中實現的,先看ObserverWrapper的屬性,ObserverWrapper不僅封裝了監聽者,還用mActive管理是否爲活躍狀態,以及用mLastVersion管理監聽者當前的數據版本。回到activeStateChanged()方法,這裏的處理主要分三點,首先,用活躍狀態是否發生變化做了一個閉路邏輯,防止重複處理,比如onStart()處理後又接收到onResume()。其次,更新當前狀態,並判斷如果這是第一個監聽者活躍,就調用onActive()方法,如果是最後一個監聽者非活躍,就調用onInactive()方法。最後,如果是新的活躍狀態,則以當前ObserverWrapper對象爲參數值調用dispatchingValue()方法分發事件。

setValue()

@MainThread

protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

setValue()是LiveData的一個成員方法,用於在主線程中手動更新LiveData中的值,這裏先將數據版本mVersion自增後,更新mData的值,並以null爲參數值調用dispatchingValue()方法。

postValue()

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};

postValue()也是用來手動更新LiveData中的值的,不過和setValue()有區別的是,它可以在非主線程中調用。它的處理就是在保證線程安全的前提下,通知主線程調用setValue()方法更新數據。

具體細節是,定義一個volatile修飾的成員變量mPandingData,用作線程間共享數據,這個變量的默認值爲NOT_SET。通過對共享數據mPandingData的讀寫訪問進行加鎖的方式實現線程安全,同時,主線程讀取mPandingData的值後,也就被認爲是消費掉了共享數據,這時會把mPandingData設置會默認值NOT_SET,而其他線程在拿到鎖後寫入mPandingData,也就是生產共享數據時,只有之前主線程已消費掉或還未生產過共享數據,纔會向主線程發送處理消息。

這個邏輯實現了另外一個特性,當主線程還沒來得及處理消息,這時多個線程同時排隊拿鎖更新數據,主線程最終只會使用最後最新的數據去處理,調用setValue()通知監聽者。

dispatchingValue()

無論是生命週期回調的activeStateChanged()還是手動發起數據更新setValue(),最終都通過dispatchingValue()完成了數據更新的分發。

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());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

dispatchingValue()如果傳入的參數不爲null,那麼就針對該對象單獨分發,對應的就是生命週期回調的調用。而如果傳入了null,那就遍歷mObservers,對每一個監聽者完成分發。每次分發是調用considerNotify()完成。

dispatchingValue()的處理中首先使用了兩個成員變量mDispatchingValue和mDispatchInvalidated做了一個短路邏輯,這倆成員變量分別表示是否處於分發中和分發的數據是否過期。進入分發過程時,會將mDispatchingValue置爲true,mDispatchInvalidated置爲false,這時表示處於正常的分發狀態。如果在正常分發狀態時,再有新的分發請求,那麼就會將mDispatchInvalidated值爲true,正常的分發狀態便會中斷,重新開始分發。這就實現了一個特性,只對監聽者通知最新的數據。

可以使用下面的單元測試加深對該特性的理解。

@Test
public void testSetValueDuringSetValue() {
    mOwner.handleLifecycleEvent(ON_START);
    final Observer observer1 = spy(new Observer<String>() {
        @Override
        public void onChanged(String o) {
            assertThat(mInObserver, is(false));
            mInObserver = true;
            if (o.equals(("bla"))) {
                mLiveData.setValue("gt");
            }
            mInObserver = false;
        }
    });
    final Observer observer2 = spy(new FailReentranceObserver());
    mLiveData.observe(mOwner, observer1);
    mLiveData.observe(mOwner, observer2);
    mLiveData.setValue("bla");
    verify(observer1, Mockito.atMost(2))
        .onChanged("gt");
    verify(observer2, Mockito.atMost(2))
        .onChanged("gt");
}

這個單元測試在源碼庫中可以找到,有興趣的同學可以debug一下看看處理流程,後面會介紹一下這個技巧,這裏先簡單描述一下代碼執行過程。

在這個單元測試中,對於mLiveData有兩個監聽者observer1和observer2,正常情況下,當mLiveData.setValue("bla")時,dispatchingValue()對監聽者進行遍歷,兩個監聽者應該依次收到數據“bla”的通知,但是observer1在收到“bla”後,又執行mLiveData.setValue("gt")發起了新的數據更新,這個第二次dispatchingValue()便會短路,且會中斷並重啓第一次的遍歷,於是observer1會再次收到“gt”,然後纔是observer2,它只會收到“gt”。

這個流程便是保證了數據更新只通知最新的,在實際開發中如果遇到setValue()的過程中再次setValue()的情況,就需要特別注意一下這條特性。

considerNotify()

 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()) {
         observer.activeStateChanged(false);
         return;
     }
     if (observer.mLastVersion >= mVersion) {
         return;
     }
     observer.mLastVersion = mVersion;
     observer.mObserver.onChanged((T) mData);
 }

considerNotify()纔是最終發起數據更新通知的方法,這裏首先檢查了監聽者及其所處生命週期的活躍狀態,並比較了監聽者的數據版本和當前數據版本,保證了監聽者所在頁面處於前臺時並且數據版本需要更新時才發起通知。發起通知前會更新監聽者的數據版本到最新,確保數據一致。

LiveData特性

分析完這些主要方法後,便可以對LiveData的特性做一個總結了,以便在實際使用過程中更加得心應手。

1. 一個監聽者只能處於一個生命週期作用域中

2. 監聽者通過Lifecycle的特性實現頁面銷燬後自動註銷,防止內存泄漏

3. 監聽者只會在所處的頁面在前臺的情況下收到數據更新的通知

4. 由於Lifecycle的特性,監聽者如果在所處頁面在前臺的情況下,註冊進LiveData,會立即調用到considerNotify(),這時候如果LiveData的數據版本變化過,便會立即對該監聽者發送通知,這也就是所謂的粘性事件。

5. postValue()經過線程安全處理,最終通過setValue()發起數據更新通知。N次postValue()並不能保證同樣N次setValue(),post中防止了重複向主線程發消息,主線程中只會拿當前最新的值調用setValue()。

6. N次setValue()同樣不能保證活躍的監聽者被通知到N次,LiveData保證了只通知最新的數據。

自頂向下分析總結

自頂向下方法主要難點在於從類關係圖中找出要分析的核心方法及其調用關係鏈,這需要提前對該組件有一定的理解,本次LiveData的分析先使用了軟件過程的三個角度框定了方法範圍,再通過在源碼快速跳轉的方式整理出調用鏈,大家可以在自己分析時參考。確定了要分析的方法後,接下來就是細心的分析工作,需要注意的是在這個過程中要總結出其實現的特性,從而更好地指導在日常實際開發工作。

03逐類分析

逐類分析的方式適合對一個組件不瞭解的情況下使用,以期快速地掌握大概原理。整個過程就是以總結類功能爲目的,對組件的相關類逐個通過跳轉方法進入,快速閱讀並做出總結,掌握類功能定義,爲以後使用其它方式進一步理解源碼做好準備。下面以這個方式分析一下ViewModel的源碼。

首先,還是先看一個例子:

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}
public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);
    }
}

該例子定義了一個ViewModel的子類MyViewModel,然後通過ViewModelProvider的實例方法get()獲取到MyViewModel的實例。

ViewModelProvider

/**

 * Creates {@code ViewModelProvider}. This will create {@code ViewModels}
 * and retain them in a store of the given {@code ViewModelStoreOwner}.
 * <p>
 * This method will use the
 * {@link HasDefaultViewModelProviderFactory#getDefaultViewModelProviderFactory() default factory}
 * if the owner implements {@link HasDefaultViewModelProviderFactory}. Otherwise, a
 * {@link NewInstanceFactory} will be used.
 */
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
    this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
         ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
         : NewInstanceFactory.getInstance());
}
/**
 * Creates {@code ViewModelProvider}, which will create {@code ViewModels} via the given
 * {@code Factory} and retain them in the given {@code store}.
 *
 * @param store   {@code ViewModelStore} where ViewModels will be stored.
 * @param factory factory a {@code Factory} which will be used to instantiate
 *                new {@code ViewModels}
 */
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
    mFactory = factory;
    mViewModelStore = store;
}

從構造方法中可以看出ViewModelProvider需要ViewModelStore和Factory兩個類型的成員變量才能構造處理,分別是mViewModelStore和mFactory,ComponentActivity和Fragment分別都實現了ViewModelStoreOwner和HasDefaultViewModelProviderFactory接口,所以都可以從中獲取到ViewModelStore和Factory的實例。

@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);
}
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
    ViewModel viewModel = mViewModelStore.get(key);

    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);
    } else {
        viewModel = mFactory.create(modelClass);
    }
    mViewModelStore.put(key, viewModel);
    return (T) viewModel;
}

get()方法首先嚐試通過mViewModelStore的get()方法獲取ViewModel的實例,如果沒獲取到則使用mFactory的create()創建實例,創建出來後則存入到mViewModelStore中。在這裏mFactory就是ViewModel的構造工廠,mViewModelStore則是ViewModel的緩存管理者。

ViewModelProvider作爲ViewModel的提供者,使用緩存mViewModelStore和工廠mFactory實現,第一次提供ViewModel時會通過工廠創建出來,後續則都是從緩存中拿。

ViewModelStore

public ComponentActivity() {

        ...
        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();
                }
            }
        }
    });
}
@NonNull
@Override
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) {
        NonConfigurationInstances nc =
            (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            // Restore the ViewModelStore from NonConfigurationInstances
            mViewModelStore = nc.viewModelStore;
        }
        if (mViewModelStore == null) {
            mViewModelStore = new ViewModelStore();
        }
    }
    return mViewModelStore;
}

ViewModelStoreOwner接口getViewModelStore()的實現就是提供一個ViewModelStore實例,而ComponentActivity使用Lifecycle能力在頁面銷燬時調用ViewModelStore實例的clear方法,清空其中的ViewModel。

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);
    }

    Set<String> keys() {
        return new HashSet<>(mMap.keySet());
    }

    /**
     *  Clears internal storage and notifies ViewModels that they are no longer used.
     */
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}

ViewModelStore中使用HashMap管理ViewModel緩存,它被頁面持有,並在頁面真正銷燬時才清空緩存。

官網的這張圖中可以說明ViewModel的生命週期。

SaveStateViewModelFactory

public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {

    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 (mDefaultFactory == null) {
        mDefaultFactory = new SavedStateViewModelFactory(
            getApplication(),
            this,
            getIntent() != null ? getIntent().getExtras() : null);
    }
    return mDefaultFactory;
}

ComponentActivity中getDefaultViewModelProviderFactory()方法通過構造方法創建一個SavedStateViewModelFactory對象,傳入了Application、當前ComponentActivity實例和Intent中的數據bundle。

<meta charset="utf-8">

SavedStateViewModelFactory構造方法

public SavedStateViewModelFactory(@NonNull Application application,
                                  @NonNull SavedStateRegistryOwner owner,
                                  @Nullable Bundle defaultArgs) {
    mSavedStateRegistry = owner.getSavedStateRegistry();
    mLifecycle = owner.getLifecycle();
    mDefaultArgs = defaultArgs;
    mApplication = application;
    mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}

構造方法接受的參數中,頁面實例是SavedStateRegistryOwner接口類型的,通過該接口獲取到SavedStateRegistry和Lifecycle。另外成員變量mFactory是AndroidViewModelFactory的單例對象。

SavedStateViewModelFactory的create()

@Override
public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
    boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
    Constructor<T> constructor;
    if (isAndroidViewModel) {
        constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
    } else {
        constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
    }
    // doesn't need SavedStateHandle
    if (constructor == null) {
        return mFactory.create(modelClass);
    }

    SavedStateHandleController controller = SavedStateHandleController.create(
        mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
    try {
        T viewmodel;
        if (isAndroidViewModel) {
            viewmodel = constructor.newInstance(mApplication, controller.getHandle());
        } else {
            viewmodel = constructor.newInstance(controller.getHandle());
        }
        viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
        return viewmodel;
    } catch (IllegalAccessException e) {
        throw new RuntimeException("Failed to access " + modelClass, e);
    } catch (InstantiationException e) {
        throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
    } catch (InvocationTargetException e) {
        throw new RuntimeException("An exception happened in constructor of "
                                   + modelClass, e.getCause());
    }
}

create()方法支持創建三種類型的ViewModel:AndroidViewModel、支持SavedState的ViewModel、普通ViewModel,這裏由於篇幅原因,只分析一下普通ViewModel的創建。普通ViewModel通過mFactory的create()方法創建出來。

AndroidViewModelFactory的create()

public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {

    ...
    @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 (NoSuchMethodException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (InstantiationException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            }
        }
        return super.create(modelClass);
    }
}

AndroidViewModelFactory的create()方法判斷如果不是AndroidViewModel類型,就直接通過父類的create()方法創建,而AndroidViewModelFactory的父類是NewInstanceFactory。

NewInstanceFactory的create()

public static class NewInstanceFactory implements Factory {
    ...

    @SuppressWarnings("ClassNewInstance")
    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        //noinspection TryWithIdenticalCatches
        try {
            return modelClass.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException("Cannot create an instance of " + modelClass, e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Cannot create an instance of " + modelClass, e);
        }
    }
}

NewInstanceFactory的create()則是直接通過反射創建出ViewModel實例。

SaveStateViewModelFactory作爲ComponentActivity和Fragment提供的對象,在NewInstanceFactory的基礎上增加了對AndroidViewModel和支持SavedStated的ViewModel的創建,但對於普通的ViewModel創建,最後還是降級使用NewInstanceFactory完成。

到此,ViewModel的主要類已經分析完了,接下來可以結合類關係,一定程度上總結出對全局視角的理解。

主要類說明:

  • ViewModelProvider:ViewModel提供者
  • ViewModelStore:ViewModel緩存管理
  • ViewModelProvider.Factory:ViewModel創建工廠
  • SavedStateViewModelFactory:ViewModel創建工廠的實現
  • NewInstanceFactory:普通ViewModel創建工廠的實現

類關係描述:

ViewModel通過ViewModelProvider的get()方法獲取到,ViewModelProvider由緩存ViewModelStore和創建工廠ViewModelProvider.Factory組合而成,ViewModelStore和ViewModelProvider.Factory也是ComponentActivity的一部分,ComponentActivity通過實現ViewModelStoreOwner和HasDefaultViewModelProviderFactory兩個接口對外提供ViewModelStore和ViewModelProvider.Factory。其中,ViewModelProvider.Factory在ComponentActivity的具體實現是SavedStateViewModelFactory,SavedStateViewModelFactory一部分由AndroidViewModelFactory組合而成,它提供創建三種ViewModel的能力,其中普通ViewModel的創建是由AndroidViewModelFactory的父類NewInstanceFactory完成。

逐類分析方法總結

逐類分析重點在於抓大放小,分析每個類的主要目的是掌握該類的功能定位,達到目的即可,不要深陷到源碼細節中。在快速分析完後,結合相關的類做出總結,從而獲得整體上的瞭解,爲以後進一步源碼原理分析打好基礎。

源碼分析技巧

Android Jetpack是一個比較新的開源庫,有幾個技巧可以提高分析的效率,比如查看代碼提交記錄和使用單元測試。

01查看代碼提交記錄

比如Lifecycling的lifecycleEventObserver()方法比較複雜,剛開始不太能理解這個方法封裝註解解析後的監聽者那部分邏輯。可以使用以下方法查看這幾行的提交記錄,方便理解。

查看Annotate:

點擊相關行,查看提交信息

雙擊相關類,查看改動記錄

在改動記錄中,還可以繼續查看Annotation,理解原有的功能

可以使用該技巧先理解舊功能是什麼樣的,從而對比出這次改動所增加的特性。

以本例來說,可以看出舊getObserverConstructorType()方法是直接返回構造對象,這個構造對象可能是註解處理器生成的類的,也可能是普通監聽者需要用反射處理的類的,然後用這個構造對象創建出監聽器的封裝。而這次修改了getObserverConstructorType()返回爲解析後的結果類型,包括REFLECTIVE_CALLBACK和GENERATED_CALLBACK,再用這個類型和getObserverConstructorType()方法中解析的緩存判斷應該創建哪個監聽器的封裝對象。這次增加的功能點是對實現多個LifecycleObserver接口的監聽器的支持,可以在單元測試類GeneratedAdapterTest中找到具體使用示例。

interface OnPauses extends LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    void onPause();

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    void onPause(LifecycleOwner owner);
}

interface OnPauseResume extends LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    void onPause();

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    void onResume();
}

class Impl1 implements OnPauses, OnPauseResume {

    List<String> mLog;

    Impl1(List<String> log) {
        mLog = log;
    }

    @Override
    public void onPause() {
        mLog.add("onPause_0");
    }

    @Override
    public void onResume() {
        mLog.add("onResume");
    }

    @Override
    public void onPause(LifecycleOwner owner) {
        mLog.add("onPause_1");
    }
}

比如上面的Impl1實現了OnPauses和OnPauseResume兩個LifecycleObserver接口,這次增加的功能點就是對Impl1也可以使用註解解析器生成封裝類,以優化性能。

02使用單元測試用例

JetPack中的單元測試非常豐富,而且從提交信息中一般都可以看到本次改動對應修改的單元測試類,比如上面的例子中,Commit Message可以看到“Test: GeneratedAdaptersTest”,可以很快定位到該單元測試,再加上斷點調試的手段,更快地理解源碼。

比如,之前一直有提到註解解析器生成的監聽器封裝類,那這個類具體代碼是什麼樣的呢,就可以在GeneratedAdaptersTest找到使用註解的實例,再通過斷點找到這個類。

debug運行testOnAny()測試

通過堆棧可以定位到GeneratedAdaptersTest_TestObserver_LifecycleAdapter類,

public class GeneratedAdaptersTest_TestObserver_LifecycleAdapter implements GeneratedAdapter {
  final GeneratedAdaptersTest.TestObserver mReceiver;

  GeneratedAdaptersTest_TestObserver_LifecycleAdapter(GeneratedAdaptersTest.TestObserver receiver) {
    this.mReceiver = receiver;
  }

  @Override
  public void callMethods(LifecycleOwner owner, Lifecycle.Event event, boolean onAny,
      MethodCallsLogger logger) {
    boolean hasLogger = logger != null;
    if (onAny) {
      if (!hasLogger || logger.approveCall("onAny", 1)) {
        mReceiver.onAny();
      }
      return;
    }
    if (event == Lifecycle.Event.ON_CREATE) {
      if (!hasLogger || logger.approveCall("onCreate", 1)) {
        mReceiver.onCreate();
      }
      return;
    }
  }
}

該類既是註解解析器生成的監聽器封裝類,它的callMethods()方法的實現由TestObserver的註解決定,TestObserver中使用了ON_CREATE和ON_ANY註解,所以除了onAny爲true的情況,callMethods()只回調監聽者的onCreate()方法。

註解處理器的實現可以定位到lifecycle-compiler項目中看,這裏限於篇幅就不展開了。

總結

本文以Lifecycle、LiveData和ViewModel三個組件,分別介紹了自底向上、自頂向下和逐類分析三種分析方法,以及查看代碼提交記錄和使用單元測試用例兩個簡單的技巧。需要說明的是,分析方法和技巧都不是獨立的,比如逐類分析其實就是簡單版的自底向上,只不過它更適合在對一個組件不太瞭解的情況下快速掌握大概原理,使用逐類分析掌握基本原理後,還可以繼續採用自頂向下的方法再分析一遍,以便更好地掌握組件的特性,減少實際工作中踩坑的可能。

而在分析源碼後,對分析方法和技巧做一些總結,可以使得分析工作的效率越來越高。大家如果有其它想法和心得,歡迎和我交流。

文末

紙上說來終覺淺,時間比較充裕的小夥伴建議去B站觀看第三方庫系列視頻講解:Android第三方開源庫系列

Jetpack組件全家桶視頻講解:Android第三方開源庫系列—Jetpack全家桶(已完結)

歡迎關注我的簡書,分享Android乾貨,交流Android技術。
對文章有何見解,或者有何技術問題,都可以在評論區一起留言討論,我會虔誠爲你解答。
也歡迎大家來我的B站找我玩,有各類Android架構師進階技術難點的視頻講解
B站直通車:https://space.bilibili.com/544650554

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章