一文搞懂Android JetPack組件原理之Lifecycle、LiveData、ViewModel與源碼分析技巧

原文鏈接:https://www.androidos.net.cn/doc/2020/9/26/478.html

好文推薦

前言

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

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

源碼下載

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

1. 安裝repo

mkdir~/binPATH=~/bin:$PATHcurl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repochmod a+x~/bin/repo

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

git config --global user.name"Your Name"git config --global user.email"you@example.com"pet__string">"you@example.com"

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

mkdir androidx-master-dev

cd androidx-master-dev

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

repoinit-u https://android.googlesource.com/platform/manifest-b androidx-master-devrepo 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的實例。

MyObserverimplementsLifecycleObserver{@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)publicvoidconnectListener(){...}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)publicvoiddisconnectListener(){...}}lifecycleOwner.getLifecycle().addObserver(newMyObserver());

LiveData

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

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

MutableLiveData<String>liveString=newMutableLiveData<>();liveString.observe(mOwner,newObserver<String>(){@OverridepublicvoidonChanged(@NullablefinalString 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處理界面就好,這樣就做到了界面和數據的分離。

publicclassMyViewModelextendsViewModel{privateMutableLiveData<List<User>>users;publicLiveData<List<User>>getUsers(){if(users==null){users=newMutableLiveData<List<User>>();loadUsers();}returnusers;}privatevoidloadUsers(){// 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的源碼。

提出問題

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

MyObserverimplementsLifecycleObserver{@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)publicvoidconnectListener(){...}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)publicvoiddisconnectListener(){...}}lifecycleOwner.getLifecycle().addObserver(newMyObserver());

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

探究答案

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

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

ComponentActiivty相關代碼

publicclassComponentActivityextendsActivityimplementsLifecycleOwner,Component{privateLifecycleRegistrymLifecycleRegistry=newLifecycleRegistry(this);protectedvoidonCreate(@NullableBundlesavedInstanceState){super.onCreate(savedInstanceState);ReportFragment.injectIfNeededIn(this);}@CallSuperprotectedvoidonSaveInstanceState(BundleoutState){Lifecyclelifecycle=this.getLifecycle();if(lifecycleinstanceofLifecycleRegistry){((LifecycleRegistry)lifecycle).setCurrentState(State.CREATED);}super.onSaveInstanceState(outState);}publicLifecyclegetLifecycle(){returnthis.mLifecycleRegistry;}}

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

ReportFragment的主要實現

publicclassReportFragmentextendsFragment{privatestaticfinalStringREPORT_FRAGMENT_TAG="android.arch.lifecycle"+".LifecycleDispatcher.report_fragment_tag";publicstaticvoidinjectIfNeededIn(Activityactivity){if(Build.VERSION.SDK_INT>=29){// On API 29+, we can register for the correct Lifecycle callbacks directlyactivity.registerActivityLifecycleCallbacks(newLifecycleCallbacks());}// 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 eventsandroid.app.FragmentManagermanager=activity.getFragmentManager();if(manager.findFragmentByTag(REPORT_FRAGMENT_TAG)==null){manager.beginTransaction().add(newReportFragment(),REPORT_FRAGMENT_TAG).commit();// Hopefully, we are the first to make a transaction.manager.executePendingTransactions();}}//...@OverridepublicvoidonStart(){super.onStart();dispatchStart(mProcessListener);dispatch(Lifecycle.Event.ON_START);}privatevoiddispatch(@NonNullLifecycle.Eventevent){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.injectIfNeededIndispatch(getActivity(),event);}}staticvoiddispatch(@NonNullActivityactivity,@NonNullLifecycle.Eventevent){if(activityinstanceofLifecycleRegistryOwner){((LifecycleRegistryOwner)activity).getLifecycle().handleLifecycleEvent(event);return;}if(activityinstanceofLifecycleOwner){Lifecyclelifecycle=((LifecycleOwner)activity).getLifecycle();if(lifecycleinstanceofLifecycleRegistry){((LifecycleRegistry)lifecycle).handleLifecycleEvent(event);}}}//...}

靜態方法injectIfNeededIn的主要作用就是為Activity提供Lifecycle能力,這里分成了兩種情況,在Android

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

Lifecycle.Event經過哪些處理

LifecycRegistry

publicclassLifecycleRegistryextends 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),

? ? */privateFastSafeIterableMap<LifecycleObserver,ObserverWithState>mObserverMap=newFastSafeIterableMap<>();privateStatemState;privatefinal WeakReference<LifecycleOwner>mLifecycleOwner;publicLifecycleRegistry(@NonNullLifecycleOwnerprovider){mLifecycleOwner=newWeakReference<>(provider);mState=INITIALIZED;}publicvoidhandleLifecycleEvent(@NonNullLifecycle.Eventevent){Statenext=getStateAfter(event);moveToState(next);}privatevoidmoveToState(Statenext){if(mState==next){return;}mState=next;......sync();......}...}

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

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

staticStategetStateAfter(Eventevent){switch(event){caseON_CREATE:caseON_STOP:returnState.CREATED;caseON_START:caseON_PAUSE:returnState.STARTED;caseON_RESUME:returnState.RESUMED;caseON_DESTROY:returnState.DESTROYED;caseON_ANY:default:thrownewIllegalArgumentException("Unexpected event value "+event);}}

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

image.png

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=newFastSafeIterableMap<>();

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

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

staticclassObserverWithState{StatemState;LifecycleEventObservermLifecycleObserver;ObserverWithState(LifecycleObserverobserver,StateinitialState){mLifecycleObserver=Lifecycling.lifecycleEventObserver(observer);mState=initialState;}voiddispatchEvent(LifecycleOwnerowner,Eventevent){StatenewState=getStateAfter(event);mState=min(mState,newState);mLifecycleObserver.onStateChanged(owner,event);mState=newState;}}

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

privatevoidsync(){LifecycleOwnerlifecycleOwner=mLifecycleOwner.get();if(lifecycleOwner==null){thrownewIllegalStateException("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()分發升級事件。

privatevoidbackwardPass(LifecycleOwnerlifecycleOwner){Iterator<Entry<LifecycleObserver,ObserverWithState>>descendingIterator=mObserverMap.descendingIterator();while(descendingIterator.hasNext()&&!mNewEventOccurred){Entry<LifecycleObserver,ObserverWithState>entry=descendingIterator.next();ObserverWithStateobserver=entry.getValue();while((observer.mState.compareTo(mState)>0&&!mNewEventOccurred&&mObserverMap.contains(entry.getKey()))){Eventevent=downEvent(observer.mState);pushParentState(getStateAfter(event));observer.dispatchEvent(lifecycleOwner,event);popParentState();}}}privatevoidforwardPass(LifecycleOwnerlifecycleOwner){Iterator<Entry<LifecycleObserver,ObserverWithState>>ascendingIterator=mObserverMap.iteratorWithAdditions();while(ascendingIterator.hasNext()&&!mNewEventOccurred){Entry<LifecycleObserver,ObserverWithState>entry=ascendingIterator.next();ObserverWithStateobserver=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的狀態都與當前狀態一致為止。

privatestaticEventdownEvent(State state){switch(state){caseINITIALIZED:thrownewIllegalArgumentException();caseCREATED:returnON_DESTROY;caseSTARTED:returnON_STOP;caseRESUMED:returnON_PAUSE;caseDESTROYED:thrownewIllegalArgumentException();}thrownewIllegalArgumentException("Unexpected state value "+state);}privatestaticEventupEvent(State state){switch(state){caseINITIALIZED:caseDESTROYED:returnON_CREATE;caseCREATED:returnON_START;caseSTARTED:returnON_RESUME;caseRESUMED:thrownewIllegalArgumentException();}thrownewIllegalArgumentException("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()對傳入的監聽者進行了處理,接下來就來看看該方法是怎么實現的。

staticLifecycleEventObserverlifecycleEventObserver(Objectobject){boolean isLifecycleEventObserver=objectinstanceof LifecycleEventObserver;boolean isFullLifecycleObserver=objectinstanceof FullLifecycleObserver;if(isLifecycleEventObserver&&isFullLifecycleObserver){returnnewFullLifecycleObserverAdapter((FullLifecycleObserver)object,(LifecycleEventObserver)object);}if(isFullLifecycleObserver){returnnewFullLifecycleObserverAdapter((FullLifecycleObserver)object,null);}if(isLifecycleEventObserver){return(LifecycleEventObserver)object;}final Class<?>klass=object.getClass();inttype=getObserverConstructorType(klass);if(type==GENERATED_CALLBACK){List<Constructor<?extends GeneratedAdapter>>constructors=sClassToAdapters.get(klass);if(constructors.size()==1){GeneratedAdaptergeneratedAdapter=createGeneratedAdapter(constructors.get(0),object);returnnewSingleGeneratedAdapterObserver(generatedAdapter);}GeneratedAdapter[]adapters=newGeneratedAdapter[constructors.size()];for(inti=0;i<constructors.size();i++){adapters[i]=createGeneratedAdapter(constructors.get(i),object);}returnnewCompositeGeneratedAdaptersObserver(adapters);}returnnewReflectiveGenericLifecycleObserver(object);}

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

直接定位到ReflectiveGenericLifecycleObserver類。

classReflectiveGenericLifecycleObserverimplementsLifecycleEventObserver{privatefinalObject mWrapped;privatefinalCallbackInfo mInfo;ReflectiveGenericLifecycleObserver(Object wrapped){mWrapped=wrapped;mInfo=ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());}@OverridepublicvoidonStateChanged(@NonNullLifecycleOwner source,@NonNullEvent event){mInfo.invokeCallbacks(source,event,mWrapped);}}

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

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

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

privateCallbackInfocreateInfo(Class<?>klass,@NullableMethod[]declaredMethods){Map<MethodReference,Lifecycle.Event>handlerToEvent=newHashMap<>();...Method[]methods=declaredMethods!=null?declaredMethods:getDeclaredMethods(klass);for(Methodmethod:methods){OnLifecycleEventannotation=method.getAnnotation(OnLifecycleEvent.class);if(annotation==null){continue;}hasLifecycleMethods=true;Class<?>[]params=method.getParameterTypes();intcallType=CALL_TYPE_NO_ARG;if(params.length>0){callType=CALL_TYPE_PROVIDER;if(!params[0].isAssignableFrom(LifecycleOwner.class)){thrownewIllegalArgumentException("invalid parameter type. Must be one and instanceof LifecycleOwner");}}Lifecycle.Eventevent=annotation.value();if(params.length>1){callType=CALL_TYPE_PROVIDER_WITH_EVENT;if(!params[1].isAssignableFrom(Lifecycle.Event.class)){thrownewIllegalArgumentException("invalid parameter type. second arg must be an event");}if(event!=Lifecycle.Event.ON_ANY){thrownewIllegalArgumentException("Second arg is supported only for ON_ANY value");}}if(params.length>2){thrownewIllegalArgumentException("cannot have more than 2 params");}MethodReferencemethodReference=newMethodReference(callType,method);verifyAndPutHandler(handlerToEvent,methodReference,event,klass);}CallbackInfoinfo=newCallbackInfo(handlerToEvent);mCallbackMap.put(klass,info);mHasLifecycleMethods.put(klass,hasLifecycleMethods);returninfo;}

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對象。

staticclassCallbackInfo{final Map<Lifecycle.Event,List<MethodReference>>mEventToHandlers;final Map<MethodReference,Lifecycle.Event>mHandlerToEvent;CallbackInfo(Map<MethodReference,Lifecycle.Event>handlerToEvent){mHandlerToEvent=handlerToEvent;mEventToHandlers=newHashMap<>();for(Map.Entry<MethodReference,Lifecycle.Event>entry:handlerToEvent.entrySet()){Lifecycle.Eventevent=entry.getValue();List<MethodReference>methodReferences=mEventToHandlers.get(event);if(methodReferences==null){methodReferences=newArrayList<>();mEventToHandlers.put(event,methodReferences);}methodReferences.add(entry.getKey());}}@SuppressWarnings("ConstantConditions")voidinvokeCallbacks(LifecycleOwnersource,Lifecycle.Eventevent,Objecttarget){invokeMethodsForEvent(mEventToHandlers.get(event),source,event,target);invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY),source,event,target);}privatestaticvoidinvokeMethodsForEvent(List<MethodReference>handlers,LifecycleOwnersource,Lifecycle.Eventevent,ObjectmWrapped){if(handlers!=null){for(inti=handlers.size()-1;i>=0;i--){handlers.get(i).invokeCallback(source,event,mWrapped);}}}}

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

staticfinalclassMethodReference{finalint mCallType;finalMethod mMethod;MethodReference(int callType,Method method){mCallType=callType;mMethod=method;mMethod.setAccessible(true);}voidinvokeCallback(LifecycleOwner source,Lifecycle.Event event,Object target){//noinspection TryWithIdenticalCatchestry{switch(mCallType){caseCALL_TYPE_NO_ARG:mMethod.invoke(target);break;caseCALL_TYPE_PROVIDER:mMethod.invoke(target,source);break;caseCALL_TYPE_PROVIDER_WITH_EVENT:mMethod.invoke(target,source,event);break;}}catch(InvocationTargetExceptione){thrownewRuntimeException("Failed to call observer method",e.getCause());}catch(IllegalAccessExceptione){thrownewRuntimeException(e);}}...}

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

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

類關系圖

該圖使用simpleUML工具生成

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

lifecycleOwner.getLifecycle().addObserver(newMyObserver());

首先,通過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=newMutableLiveData<>();liveString.observe(mOwner,newObserver<String>(){@OverridepublicvoidonChanged(@NullablefinalString 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()注冊監聽者

@MainThreadpublicvoidobserve(@NonNull LifecycleOwner owner,@NonNull Observer<?superT>observer){assertMainThread("observe");if(owner.getLifecycle().getCurrentState()==DESTROYED){// ignorereturn;}LifecycleBoundObserver wrapper=newLifecycleBoundObserver(owner,observer);ObserverWrapper existing=mObservers.putIfAbsent(observer,wrapper);if(existing!=null&&!existing.isAttachedTo(owner)){thrownewIllegalArgumentException("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()

classLifecycleBoundObserverextendsObserverWrapperimplementsLifecycleEventObserver{@NonNullfinalLifecycleOwnermOwner;LifecycleBoundObserver(@NonNullLifecycleOwnerowner,Observer<?superT>observer){super(observer);mOwner=owner;}@OverridebooleanshouldBeActive(){returnmOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}@OverridepublicvoidonStateChanged(@NonNullLifecycleOwnersource,@NonNullLifecycle.Eventevent){if(mOwner.getLifecycle().getCurrentState()==DESTROYED){removeObserver(mObserver);return;}activeStateChanged(shouldBeActive());}@OverridebooleanisAttachedTo(LifecycleOwnerowner){returnmOwner==owner;}@OverridevoiddetachObserver(){mOwner.getLifecycle().removeObserver(this);}}

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

ObserverWrapper的activeStateChanged()

privateabstractclassObserverWrapper{finalObserver<?superT>mObserver;booleanmActive;intmLastVersion=START_VERSION;ObserverWrapper(Observer<?superT>observer){mObserver=observer;}abstractbooleanshouldBeActive();booleanisAttachedTo(LifecycleOwnerowner){returnfalse;}voiddetachObserver(){}voidactiveStateChanged(booleannewActive){if(newActive==mActive){return;}// immediately set active state, so we'd never dispatch anything to inactive// ownermActive=newActive;booleanwasInactive=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()

@MainThreadprotectedvoidsetValue(Tvalue){assertMainThread("setValue");mVersion++;mData=value;dispatchingValue(null);}

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

postValue()

protectedvoidpostValue(Tvalue){booleanpostTask;synchronized(mDataLock){postTask=mPendingData==NOT_SET;mPendingData=value;}if(!postTask){return;}ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);}privatefinalRunnablemPostValueRunnable=newRunnable(){@SuppressWarnings("unchecked")@Overridepublicvoidrun(){ObjectnewValue;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()完成了數據更新的分發。

voiddispatchingValue(@NullableObserverWrapper initiator){if(mDispatchingValue){mDispatchInvalidated=true;return;}mDispatchingValue=true;do{mDispatchInvalidated=false;if(initiator!=null){considerNotify(initiator);initiator=null;}else{for(Iterator<Map.Entry<Observer<?superT>,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,正常的分發狀態便會中斷,重新開始分發。這就實現了一個特性,只對監聽者通知最新的數據。

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

@TestpublicvoidtestSetValueDuringSetValue(){mOwner.handleLifecycleEvent(ON_START);finalObserverobserver1=spy(newObserver<String>(){@OverridepublicvoidonChanged(Stringo){assertThat(mInObserver,is(false));mInObserver=true;if(o.equals(("bla"))){mLiveData.setValue("gt");}mInObserver=false;}});finalObserverobserver2=spy(newFailReentranceObserver());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()

privatevoidconsiderNotify(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的源碼。

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

publicclassMyViewModelextendsViewModel{privateMutableLiveData<List<User>>users;publicLiveData<List<User>>getUsers(){if(users==null){users=newMutableLiveData<List<User>>();loadUsers();}returnusers;}privatevoidloadUsers(){// Do an asynchronous operation to fetch users.}}publicclassMyActivityextendsAppCompatActivity{publicvoidonCreate(BundlesavedInstanceState){MyViewModelmodel=newViewModelProvider(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.

*/publicViewModelProvider(@NonNullViewModelStoreOwner 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}

*/publicViewModelProvider(@NonNullViewModelStore store,@NonNullFactory factory){mFactory=factory;mViewModelStore=store;}

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

@NonNull@MainThreadpublic<TextendsViewModel> T get(@NonNull Class<T> modelClass) {String canonicalName=modelClass.getCanonicalName();if(canonicalName==null){thrownewIllegalArgumentException("Local and anonymous classes can not be ViewModels");}returnget(DEFAULT_KEY+":"+canonicalName,modelClass);}@MainThread

public <TextendsViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {ViewModel viewModel=mViewModelStore.get(key);if(modelClass.isInstance(viewModel)){if(mFactoryinstanceofOnRequeryFactory){((OnRequeryFactory)mFactory).onRequery(viewModel);}return(T)viewModel;}else{//noinspection StatementWithEmptyBodyif(viewModel!=null){// TODO: log a warning.}}if(mFactoryinstanceofKeyedFactory){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

publicComponentActivity(){...getLifecycle().addObserver(newLifecycleEventObserver(){@OverridepublicvoidonStateChanged(@NonNullLifecycleOwnersource,@NonNullLifecycle.Eventevent){if(event==Lifecycle.Event.ON_DESTROY){if(!isChangingConfigurations()){getViewModelStore().clear();}}}});}@NonNull@OverridepublicViewModelStoregetViewModelStore(){if(getApplication()==null){thrownewIllegalStateException("Your activity is not yet attached to the "+"Application instance. You can't request ViewModel before onCreate call.");}if(mViewModelStore==null){NonConfigurationInstancesnc=(NonConfigurationInstances)getLastNonConfigurationInstance();if(nc!=null){// Restore the ViewModelStore from NonConfigurationInstancesmViewModelStore=nc.viewModelStore;}if(mViewModelStore==null){mViewModelStore=newViewModelStore();}}returnmViewModelStore;}

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

publicclassViewModelStore{privatefinalHashMap<String,ViewModel>mMap=newHashMap<>();finalvoidput(String key,ViewModel viewModel){ViewModel oldViewModel=mMap.put(key,viewModel);if(oldViewModel!=null){oldViewModel.onCleared();}}finalViewModelget(String key){returnmMap.get(key);}Set<String>keys(){returnnewHashSet<>(mMap.keySet());}/**

? ? *? Clears internal storage and notifies ViewModels that they are no longer used.

? ? */publicfinalvoidclear(){for(ViewModel vm:mMap.values()){vm.clear();}mMap.clear();}}

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

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

SaveStateViewModelFactory

publicViewModelProvider.FactorygetDefaultViewModelProviderFactory(){if(getApplication()==null){thrownewIllegalStateException("Your activity is not yet attached to the "+"Application instance. You can't request ViewModel before onCreate call.");}if(mDefaultFactory==null){mDefaultFactory=newSavedStateViewModelFactory(getApplication(),this,getIntent()!=null?getIntent().getExtras():null);}returnmDefaultFactory;}

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

SavedStateViewModelFactory構造方法

publicSavedStateViewModelFactory(@NonNullApplication application,@NonNullSavedStateRegistryOwner owner,@NullableBundle defaultArgs){mSavedStateRegistry=owner.getSavedStateRegistry();mLifecycle=owner.getLifecycle();mDefaultArgs=defaultArgs;mApplication=application;mFactory=ViewModelProvider.AndroidViewModelFactory.getInstance(application);}

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

SavedStateViewModelFactory的create()

@Overridepublic<TextendsViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {booleanisAndroidViewModel=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) {returnmFactory.create(modelClass);}? ? SavedStateHandleController controller = SavedStateHandleController.create(

? ? ? ? mSavedStateRegistry, mLifecycle, key, mDefaultArgs);

? ? try {Tviewmodel;if(isAndroidViewModel){viewmodel=constructor.newInstance(mApplication,controller.getHandle());}else{viewmodel=constructor.newInstance(controller.getHandle());}viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER,controller);returnviewmodel;} catch (IllegalAccessException e) {thrownewRuntimeException("Failed to access "+modelClass,e);} catch (InstantiationException e) {thrownewRuntimeException("A "+modelClass+" cannot be instantiated.",e);} catch (InvocationTargetException e) {thrownewRuntimeException("An exception happened in constructor of "+modelClass,e.getCause());}}

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

AndroidViewModelFactory的create()

publicstaticclassAndroidViewModelFactoryextendsViewModelProvider.NewInstanceFactory{...@NonNull@Overridepublic<TextendsViewModel>Tcreate(@NonNullClass<T>modelClass){if(AndroidViewModel.class.isAssignableFrom(modelClass)){//noinspection TryWithIdenticalCatchestry{returnmodelClass.getConstructor(Application.class).newInstance(mApplication);}catch(NoSuchMethodExceptione){thrownewRuntimeException("Cannot create an instance of "+modelClass,e);}catch(IllegalAccessExceptione){thrownewRuntimeException("Cannot create an instance of "+modelClass,e);}catch(InstantiationExceptione){thrownewRuntimeException("Cannot create an instance of "+modelClass,e);}catch(InvocationTargetExceptione){thrownewRuntimeException("Cannot create an instance of "+modelClass,e);}}returnsuper.create(modelClass);}}

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

NewInstanceFactory的create()

publicstaticclassNewInstanceFactoryimplementsFactory{...@SuppressWarnings("ClassNewInstance")@NonNull@Overridepublic<TextendsViewModel>Tcreate(@NonNullClass<T>modelClass){//noinspection TryWithIdenticalCatchestry{returnmodelClass.newInstance();}catch(InstantiationExceptione){thrownewRuntimeException("Cannot create an instance of "+modelClass,e);}catch(IllegalAccessExceptione){thrownewRuntimeException("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中找到具體使用示例。

interfaceOnPausesextendsLifecycleObserver{@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)voidonPause();@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)voidonPause(LifecycleOwnerowner);}interfaceOnPauseResumeextendsLifecycleObserver{@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)voidonPause();@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)voidonResume();}classImpl1implementsOnPauses,OnPauseResume{List<String>mLog;Impl1(List<String>log){mLog=log;}@OverridepublicvoidonPause(){mLog.add("onPause_0");}@OverridepublicvoidonResume(){mLog.add("onResume");}@OverridepublicvoidonPause(LifecycleOwnerowner){mLog.add("onPause_1");}}

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

02使用單元測試用例

JetPack中的單元測試非常豐富,而且從提交信息中一般都可以看到本次改動對應修改的單元測試類,比如上面的例子中,Commit

Message可以看到“Test:

GeneratedAdaptersTest”,可以很快定位到該單元測試,再加上斷點調試的手段,更快地理解源碼。

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

debug運行testOnAny()測試

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

publicclassGeneratedAdaptersTest_TestObserver_LifecycleAdapterimplementsGeneratedAdapter{finalGeneratedAdaptersTest.TestObservermReceiver;GeneratedAdaptersTest_TestObserver_LifecycleAdapter(GeneratedAdaptersTest.TestObserverreceiver){this.mReceiver=receiver;}@OverridepublicvoidcallMethods(LifecycleOwnerowner,Lifecycle.Eventevent,booleanonAny,MethodCallsLoggerlogger){booleanhasLogger=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三個組件,分別介紹了自底向上、自頂向下和逐類分析三種分析方法,以及查看代碼提交記錄和使用單元測試用例兩個簡單的技巧。需要說明的是,分析方法和技巧都不是獨立的,比如逐類分析其實就是簡單版的自底向上,只不過它更適合在對一個組件不太了解的情況下快速掌握大概原理,使用逐類分析掌握基本原理后,還可以繼續采用自頂向下的方法再分析一遍,以便更好地掌握組件的特性,減少實際工作中踩坑的可能。

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

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內容