本文已授權我就是馬云飛公眾號獨家發布。
說是源碼分析有點,其實就是簡單的根據源碼梳理一遍整體的LiveData,ViewModel和Lifecycle各個部分是如何工作的,由于本人水平有限,如果文中有錯誤的地方,歡迎指正。
Android Architecture Components 源碼分析系列文章
- Android Architecture Components 第一篇,介紹生命周期的感知。
- Android Architecture Components 第二篇,介紹ViewModel的控制。
- Android Architecture Components 第三篇,介紹LiveDate和LifeRegistry的協同操作。
這個是Android Architecture Components(簡稱AAC)的第三篇,之前的兩篇 文章分別介紹了Lifecycle和ViewModel的生命周期,這篇主要講的就是最開始提出的第三個問題LiveData數據的控制。
簡單案例
先列舉一個簡單的例子,看看如何使用的
在ViewModel中有LiveData的成員變量,然后添加一個觀察者。在ViewModel中
在ViewModel中就是擁有一個成員變量,加上對應的get方法,修改數據的時候直接使用setValue更新,這樣就會彈出一個Toast。
使用起來并不難,但我們的目的是了解如何實現的。
案例分析
關于上文的例子,從三個部分開始分析,一是添加觀察者的時候,二是生命周期的控制,三是設置數據的時候。
添加觀察者
- 先判斷一下LifecycleRegistry當前的狀態,如果是DESTORYED的話,就直接返回。
- 之后是將LifecycleOwner和創建Observer封裝到LifecycleBoundObserver中。
- 從當前的Oberver集合中查找沒有傳入的Observer對應的包裝類,如果有則返回,沒有則添加。
- LifecycleRegistry添加包裝之后的LifecycleBoundObserver觀察者。
- 更新下當前的包裝類的狀態。
這里需要理解并記住的是LifecycleBoundObserver是一個擁有真正回調Observer和LifecycleOwner的封裝類。
在LifecycleRegistry中添加觀察者,這個LifecycleRegistry是在Activity/Fragment中創建的成員變量。
- 確定初始時LifecycleBoundObserverd的狀態,這里大部分的情況都是INITIALIZED,除非把之前的observe寫在onDestory中,不過估計一般沒人這么寫。
- 將傳入的LifecycleBoundObserver和確定的狀態封裝到一個statefulObserver。在這個過程中會對observer進行一定轉化,將其改變成另一種LifecycleObserver,然后再使用的時候會通過反射去調到實際需要的方法。
- 將封裝過的statefulObserver和傳入的observer添加到當前的一個map中進行保存,如果之前已經添加過的話,就直接返回舊的,沒有的話再放入,返回null。
- 判斷是否可以重入,來決定是否進行同步,這里的parentState暫時先不考慮,等最后的時候再分析。
- 其中while循環的部分是為了修改剛添加進去的ObseverWithState中state的狀態。
- sync方法是事件傳遞的關鍵,在之后也會用到,就先不分析。
接下來看一下當生命周期變化的時候會發生什么?
生命周期改變
根據第一篇文章中我們可以知道當應用的生命周期變化的時候,會發送對應的生命周期事件到LifecycleRegistry的handleLifecycleEvent方法中進行處理,這里先簡單的分析下邏輯。
首先設置當前的LifecycleRegistry中的mState值,之后執行sync方法
這里先判斷一下是否可以進行同步,判斷的條件是當前map中的oberver數量和狀態,之后會根據當前的mObserverMap中保存的observer的狀態和當前的Registry的狀態進行比較,來決定是進行正推計算還是反推計算。先以正推計算為例:
把當前的mObserverMap中的數據進行迭代,判斷狀態之后執行observer.dispatchEvent()方法,來同步Observer
這里會先設置當前的Observer的狀態,之后會調用Observer的onStateChanged方法,這個方法會經過一系列的變化,通過反射,最終調到LiveData中的LifecycleBoundObserver的onStateChage()方法
這兩個方法最主要的作用就是判斷當前的LifecycleOwner是否是active狀態。如果是active狀態的話就刷新數據。
數據更新
上面正好講到刷新數據,我們來繼續說一下當setvalue的時候發生了什么:
可以看到將成員變量mData賦值 ,之后也是調用了相同的dispatchingValue方法
這里的關鍵函數就是considerNotify,如果是通過setValue方法進行更新的話,會更新所有的observer,如果是通過handleLifecycleEvent方法進行更新的話,那么只會更改當前的observer。
首先會先檢查當前的observer的active,之后會檢查observer的owner的狀態是否是可用的,再判斷當前的版本。最后進行更新數據。
小結
到這里其實整體的生命周期事件的觀察和傳遞,同步和更新,修改數據,都已經簡單的介紹完畢了,單單拿出來一個部分其實并不難理解,主要需要明白并記住的就是LifecycleRigestry的mState、Event、ObserverWithState的mState和LifecycleBoundObserver的active。事件的來源只有一種就是handleLifecycleEvent,最終的目的地就是為了修改ObserverWithState的mState和LifecycleBoundObserver的active。
整體流程分析
每一個小部分的功能都有所了解的之后,讓我們嘗試下梳理最上面的案例中整個事件的傳遞。這里添加訂閱者是在onCreate方法中。先上個我自己畫的圖,方便理解。
這個是我自己梳理的整體的事件流程和刷新的圖。根據這個圖來介紹下執行的流程。
由于上面的案例是在onCreate中訂閱的,那么最開始先執行的應該是addObserver,這個時候會把LifecycleRegistry的mState(下文簡稱RS)置為INITIALIZED。并向observerMap中添加封裝過的ObserverWithState,其中的mState(下文簡稱OS)為INITIALIZED。不執行同步方法。
Activity啟動,傳遞過來第一個生命周期事件ON_CREATE,通過getStateAfter計算之后的State為CREATED賦值給RS,判斷狀態決定執行正推計算,OS的當前值為INITIALIZED,更改LifecycleBoundObserver的active(下文簡稱active)值為false。OS修改為CREATED。
事件ON_START,RS為STARTED,正推計算,OS當前值為CREATED,更改active為true。OS修改為STARTED。
事件ON_RESUME,RS為RESUMED,正推計算,OS當前值為STARTED,更改active為true。OS修改為RESUMED。
事件ON_PAUSE,RS為STARTED,反推計算,OS當前值為STARTED,更改active為true。OS修改為STARTED。
事件ON_STOP,RS為CREATED,反推計算,OS當前值為CREATED,更改active為false。OS修改為CREATED。
事件ON_DESTROY,RS為DESTROYED,反推計算,OS當前值為DESTROYED,更改active為false。OS修改為DESTROYED。
整體事件流程就是這樣,通過感知Activity/Fragment的生命周期,然后分發到LifecycleRegistry中進行處理,根據當前的狀態來修改保存的ObserverWithState的mState,然后修改LifecycleBoundObserver的active決定數據是否可以更新。
上面的狀態都是作者根據最開始的案例斷點調試得出的結論,值得注意的就是因為有Application也就是ProcessLifecycleOwner的干擾,調試的時候要區分好LifeRegistry,第二個注意的就是mState的值,因為有兩個mState,經常會需要進行比較,來決定同步。
總結
至此,整個Android Architecture Components架構中所有的源碼都過了一遍了, 主要的難點就是在handleLifecycleEvent()和Sync()兩個方法??傮w的分析下整個架構:
個人認為主要分為三個部分:
第一部分:生命周期的感知包括系統生命周期的感知。其中有使用的類和技巧有,通過注冊ContenProvider進行項目的初始化,通過添加Fragment來獲取宿主的生命周期。通過給Application和Activity添加生命周期的回調,來進行Fragment的初始化和生命周期的感知。
相關的類包括:
LifecycleRuntimeTrojanProvider 用于進行初始化init操作 、
LifecycleDispatcher 用于進行生命周期分發處理 、
ProcessLifecycleOwner 應用生命周期控制 ,、
ReportFragment 添加的Fragment 用于感知宿主生命周期 。
第二部分:ViewModel生命周期的控制。同樣使用了添加Fragment來感知宿主的生命周期,通過一個HoldFragment來持有一個ViewModelStore保存當前宿主的所有ViewModel,通過工廠模式反射獲得ViewModel對象。
相關的類包括:
ViewModel 、
ViewModelProvider ViewModel的提供者 、
ViewModelStore 用于保存ViewModel、
HolderFragment 添加的Fragment 用于感知宿主生命周期等。
第三部分:LiveData和LifecycleRegistry的協同操作。這里使用了兩個枚舉對象來概括整體的生命周期,通過Event的傳遞來改變當前的Lifecycyle的狀態,同時更新當前的Observer是否處于活動狀態。個人認為整個項目中的關于Observer的三個封裝類是整個項目的骨架,State和Event就是流動血液,而HandleLifecycleEvent和Sync兩個方法就是整個項目的靈魂。
相關的類包括:
LiveData 數據模型 、
LifecycleOwner 生命周期持有者 、
LifecycleRegistry 用于控制生命周期 、
ObserverWithState 保存Observer和對應的狀態 、
LifecycleBoundObserver 保存Observer和LifecycleOwner 、
ReflectiveGenericLifecycleObserver 反射調用的相關類。
學習收獲
這不是我第一次去深入的研究系統的源碼了,不過每一次看源代碼真的都能帶來新的收獲和想法。在學習AAC的過程中,最大的收獲感覺還是對AAC項目的熟悉,能夠清楚的知道每一個類,每一個方法,每一個成員變量的作用,是用來做什么的,什么起作用。當我看到它們的類名就能夠知道他們是做什么的,這種熟悉感,我覺得是最大的收獲。其次是在研究源碼過程中一些心得體會,遇到難度高的地方的時候適當的放松,真的會有助于解決問題,我這里有好幾個關鍵點都是我下樓散步的時候想到的為什么。
最后想要說的就是對于知識的渴望程度,或者說對于知識的了解程度,我覺得這種概念適用于所有領域,以AAC這個框架為例
- 會使用,能夠寫代碼
- 知道原理,了解源代碼是什么實現的,知道每一個部分的原理,功用。
- 能夠修改,在原有的基礎上進行修改,使其變得更優或者更適用于自己。
目前在學習第三方框架的時候,都在遵循著三點,爭取都能夠達到第二層次,部分簡單的項目可以實現第三層次。這好比練武功,從登堂入室,再到爛熟于心,再到推陳出新。
會用的人太多,而知道為什么的人太少。