Jetpack是2018年谷歌I/O 發(fā)布了一系列輔助android開發(fā)者的實用工具庫克锣,以幫助開發(fā)者構(gòu)建出色的 Android 應(yīng)用础米。
Jetpack 通過提供現(xiàn)代化應(yīng)用架構(gòu)以及提供強(qiáng)健的向后兼容能力等方式恐疲,讓開發(fā)者能夠快速草则、輕松地創(chuàng)造擁有卓越性能的高質(zhì)量應(yīng)潭陪。
Jetpack是Google重點打造的下一代 Android 組件雄妥,可以說它就是Android的未來方向,所以掌握好Jetpack依溯,你就掌握好了未來戰(zhàn)場的強(qiáng)大武器老厌。
本猿準(zhǔn)備通過一系列的文章去記錄我對JetPack的學(xué)習(xí)要點及心得。那么我們就從AAC開始吧黎炉。
AAC架構(gòu)一:AAC架構(gòu)簡介
AAC架構(gòu)二:AAC架構(gòu)應(yīng)用舉例
一枝秤、前言
基于目前的項目的架構(gòu)比較陳舊,而且AAC架構(gòu)也推廣了有一段時間慷嗜,基本上處于比較成熟的狀況了淀弹,于是決心下來丹壕,把架構(gòu)進(jìn)行更新。
很久之前就想開始寫點關(guān)于Jetpack這個包集相關(guān)的文章垦页,但是雀费,出于種種原因,一直擱置著痊焊,借著這次更新架構(gòu)盏袄,順便把這個心愿了了。
AAC架構(gòu)是Jetpack里比較核心的一部分薄啥,我們就從這個點出發(fā)辕羽,逐步體驗一下Jetpack的強(qiáng)大。
二垄惧、常用的架構(gòu)原則
我們先回顧一下刁愿,大家日常開放中經(jīng)常用到的架構(gòu)原則。
1到逊、分離關(guān)注點
要遵循的最重要的原則是分離關(guān)注點铣口,一種常見的錯誤是在一個 Activity
或 Fragment
中編寫所有代碼。這些基于界面的類應(yīng)僅包含處理界面和操作系統(tǒng)交互的邏輯觉壶。您應(yīng)盡可能使這些類保持精簡脑题,這樣可以避免許多與生命周期相關(guān)的問題。
請注意铜靶,您并非擁有
Activity
和Fragment
的實現(xiàn)叔遂;它們只是表示 Android 操作系統(tǒng)與應(yīng)用之間關(guān)系的粘合類。操作系統(tǒng)可能會根據(jù)用戶互動或因內(nèi)存不足等系統(tǒng)條件隨時銷毀它們争剿。為了提供令人滿意的用戶體驗和更易于管理的應(yīng)用維護(hù)體驗已艰,您最好盡量減少對它們的依賴。
2蚕苇、通過模型驅(qū)動界面
另一個重要原則是您應(yīng)該通過模型驅(qū)動界面(最好是持久性模型)哩掺。模型是負(fù)責(zé)處理應(yīng)用數(shù)據(jù)的組件。它們獨立于應(yīng)用中的 View
對象和應(yīng)用組件涩笤,因此不受應(yīng)用的生命周期以及相關(guān)的關(guān)注點的影響疮丛。
持久性是理想之選,原因如下:
- 如果 Android 操作系統(tǒng)銷毀應(yīng)用以釋放資源辆它,用戶不會丟失數(shù)據(jù)。
- 當(dāng)網(wǎng)絡(luò)連接不穩(wěn)定或不可用時履恩,應(yīng)用會繼續(xù)工作锰茉。
應(yīng)用所基于的模型類應(yīng)明確定義數(shù)據(jù)管理職責(zé),這樣將使應(yīng)用更可測試且更一致切心。
基于常見的架構(gòu)原則
飒筑,如果你的架構(gòu)非常陳舊或者比較凌亂片吊,我覺得還是非常有必要更新?lián)Q代的,這里协屡,我推薦使用ACC架構(gòu)俏脊。
三、AAC架構(gòu)
我們先來看一下定義:
Android Architecture Components,簡稱 AAC肤晓,一個處理UI的生命周期與數(shù)據(jù)的持久化的架構(gòu)爷贫,它基于管理UI組件生命周期和處理數(shù)據(jù)持久性的類,可以幫助您設(shè)計健壯补憾、可測試和可維護(hù)的應(yīng)用程序漫萄。
1、AAC 的核心
AAC架構(gòu)的核心部分包括:
Lifecycle, LiveData, ViewModel 以及 Room
-
Lifecycle幫助您管理
Activity
和Fragment
生命周期盈匾。生存配置更改腾务,避免內(nèi)存泄漏并輕松將數(shù)據(jù)加載到UI中。 - 使用LiveData 構(gòu)建數(shù)據(jù)對象削饵,以便在基礎(chǔ)數(shù)據(jù)庫更改時通知視圖岩瘦。
- ViewModel存儲在應(yīng)用程序輪換時未銷毀的UI相關(guān)數(shù)據(jù)。
- Room是一個SQLite對象映射庫窿撬。使用它來避免樣板代碼并輕松地將SQLite表數(shù)據(jù)轉(zhuǎn)換為Java對象启昧。Room提供SQLite語句的編譯時檢查,可以返回RxJava尤仍,F(xiàn)lowable和LiveData observable箫津。
優(yōu)勢
- 通過它可以非常優(yōu)雅的讓數(shù)據(jù)與界面交互
- 并做一些持久化的東西
- 高度解耦
- 自動管理生命周期
- 而且不用擔(dān)心內(nèi)存泄漏的問題.
架構(gòu)圖如下:
請注意,每個組件僅依賴于其下一級的組件宰啦。例如苏遥,Activity 和 Fragment 僅依賴于視圖模型。存儲區(qū)是唯一依賴于其他多個類的類赡模;圖中田炭,存儲區(qū)依賴于持久性數(shù)據(jù)模型和遠(yuǎn)程后端數(shù)據(jù)源。
這種設(shè)計打造了一致且愉快的用戶體驗漓柑。無論用戶上次使用應(yīng)用是在幾分鐘前還是幾天之前教硫,現(xiàn)在回到應(yīng)用時都會立即看到應(yīng)用在本地保留的用戶信息。如果此數(shù)據(jù)已過時辆布,則應(yīng)用的存儲區(qū)模塊將開始在后臺更新數(shù)據(jù)瞬矩。
注意:任何應(yīng)用編寫方式都不可能是每種情況的最佳選擇。話雖如此锋玲,但推薦的這個架構(gòu)是個不錯的起點景用,適合大多數(shù)情況和工作流。如果您已經(jīng)有編寫 Android 應(yīng)用的好方法(遵循以上提到的
常見的架構(gòu)原則
)惭蹂,則無需更改伞插。
2割粮、LifeCycle & LifecycleOwner
Lifecycle:它是一個持有 Activity/Fragment 生命周期狀態(tài)信息的類,并且允許其他對象觀察此狀態(tài)媚污。
-
LifecycleOwner:是一個具有單一方法的接口舀瓢。如果一個類實現(xiàn)了此接口,則該類中需要持有一個 Lifecycle 對象耗美,并通過LifecycleOwner.getLifecycle() 方法返回該對象京髓。
并不是只有 Activity 和 Fragment 才可以實現(xiàn) LifecycleOwner 接口的,任何和 Activity/Fragment 生命周期有關(guān)系的類都可以實現(xiàn)此接口幽歼。通過實現(xiàn)此接口朵锣,該類完全是生命周期可感知的,只需要對它進(jìn)行初始化甸私,它就可以進(jìn)行自己的初始化和清理操作诚些,而不受其 Activity/Fragment 的管理
activity活動圖:
獲取當(dāng)前activity的狀態(tài):
if(getLifecycle().getCurrentState() == Lifecycle.State.RESUMED){
//todo ...
}
3、LiveData
LiveData 是一個數(shù)據(jù)持有類皇型,它持有一個值并且該值可以被觀察诬烹。不同于普通的可觀察者,LiveData 遵從應(yīng)用組件的生命周期弃鸦,這樣 Observer 便可以指定一個其應(yīng)該遵循的 Lifecycle绞吁。
如果 Observer 所依附的 Lifecycle 處于 STARTED 或者 RESUMED 狀態(tài),則 LiveData 認(rèn)為 Observer 處于活躍狀態(tài)唬格。
可以感知組件生命周期的 LiveData 給我們提供了一種可能:可以在多個 Activity家破、Fragment 之間共享它。
使用 LiveData 會有以下幾個優(yōu)勢:
- 避免內(nèi)存泄露:因為 Observer 是綁定到 Lifecycle 對象上的购岗,當(dāng) Lifecycle 對象被銷毀的時候汰聋,LiveData 對象也會被自動清除
- 不會因為 Activity 停止而使應(yīng)用崩潰:如果 Observer 所綁定的 Lifecycle 處于閑置狀態(tài)(例如:Activity 處于后臺運行時),他們不會接收到改變的事件
- 始終保持最新的數(shù)據(jù):如果一個 Lifecycle 重新啟動以后(例如:Activity 從后臺重新開始運行于前臺)喊积,它會接收到最新的數(shù)據(jù)(除非沒有最新的數(shù)據(jù))
- 正確處理配置改變:如果一個 Activity 或者 Fragment 以為配置改變(例如:旋轉(zhuǎn)屏幕)被重建以后烹困,LiveData 將會接收到最新的數(shù)據(jù)
- 資源共享:通過單例模式,可以在多個 Activity 或者 Fragment 之間共享 LiveData 數(shù)據(jù)乾吻。
- 不再手動的處理生命周期:Fragment 只有在處于活躍的時候才會觀察 LiveData 數(shù)據(jù)髓梅。由于 Fragment 提供了 Lifecycle 對象,所以 LiveData 會管理這一切绎签。
有時候枯饿,也許想在 LiveData 被下發(fā)到 Observer 之前,改變 LiveData 的值诡必,或者是基于當(dāng)前的 LiveData 下發(fā)另一個不同的 LiveData 值鸭你。Lifecycle 包中的 Transformations 可以實現(xiàn)這樣的功能。
Transformations.map(),使用此方法袱巨,可以將 LiveData 傳遞到下游
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
user.name + " " + user.lastName
});
Transformations.switchMap(),和 map() 方法類似碳抄,使用 switchMap() 應(yīng)用于 LiveData 的值并解包愉老,然后將結(jié)果傳遞到下游。傳遞給 switchMap() 的方法必須返回一個 Lifecycle
private LiveData<User> getUser(String id) {
...;
}
LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
使用這兩個轉(zhuǎn)換剖效,允許在整個調(diào)用鏈中攜帶觀察者的 Lifecycle 信息嫉入,這樣的話,只有在觀察者觀察到 LiveData 的返回值時璧尸,才會運算這些轉(zhuǎn)換咒林。
當(dāng)你需要在 ViewModel 中添加一個 Lifecycle 對象時,Transformations 或許是一個好的解決辦法爷光。
android.arch.lifecycle.Observer
用于對LiveData增加監(jiān)聽垫竞,使用的方法為LiveData.observe(LifecycleOwner, Observer), 對于一些不需要的observer建議及時移除掉,LiveData.removeObserver(Observer),因為如果沒有移除掉蛀序,當(dāng)數(shù)據(jù)刷新的時候還是會一直調(diào)用
基于LiveData的特性欢瞪,你會發(fā)現(xiàn),它完全具備
事件總線
的要求徐裸,而且還能感知生命周期遣鼓,而且還是Google官方API,這地多帶勁呀重贺。后面準(zhǔn)備寫一個用LiveData做事件總線
的文章骑祟,替代第三方的事件總線
。
4气笙、ViewModel
ViewModel 類是用來存儲和管理 UI 相關(guān)的數(shù)據(jù)次企,這樣在配置發(fā)生變化(例如:屏幕旋轉(zhuǎn))時,數(shù)據(jù)就不會丟失健民。
由于應(yīng)用程序組件(例如:Activity抒巢、Fragment),具有一個由 Android Framework 管理的生命周期秉犹,Activity 或 Fragment 在某些情況下(比如:內(nèi)存緊張或者屏幕旋轉(zhuǎn))會發(fā)生銷毀或者重新創(chuàng)建的情況蛉谜。這樣就會帶來一些問題:
- 由于 Activity 或者 Fragment 有可能會被銷毀或重新創(chuàng)建,所以保存于其中的數(shù)據(jù)有可能會丟失
- 在 Activity 或者 Fragment 中會經(jīng)常發(fā)起一些需要一定時間才會返回結(jié)果的異步請求調(diào)用
- 如果把處理應(yīng)用數(shù)據(jù)崇堵、完成響應(yīng)用戶操作型诚、處理系統(tǒng)通信工作的代碼都寫在 Activity 或者 Fragment 中,那么 Activity 或者 Fragment 將會變得非常的臃腫鸳劳,給維護(hù)工作帶來一定的困難
針對以上問題狰贯,Lifecycle 提供了一個叫 ViewModel 的類,一個 UI 控制器的幫助類,用來為 UI 準(zhǔn)備數(shù)據(jù)涵紊。
在配置更改的時候傍妒,ViewModel 會被保留,以便其保存的數(shù)據(jù)可以立即傳遞給重新創(chuàng)建的 Activity 或者 Fragment 實例中。如果 Activity 被重新創(chuàng)建,它將會收到由之前的 Activity 或者 Fragment 創(chuàng)建的 ViewModel 實例脯厨。當(dāng)所有者 Activity 被銷毀以后,F(xiàn)ramework 會調(diào)用 ViewModel.onCleared() 清楚系統(tǒng)資源
注意:由于ViewModel超出了具體的Activity和Fragment實例生命周期嗦玖,所以它不應(yīng)該引用View或任何可能持有對活動上下文的引用的類。 如果ViewModel需要應(yīng)用程序上下文(例如跃脊,找到系統(tǒng)服務(wù))宇挫,則可以擴(kuò)展AndroidViewModel類,并在構(gòu)造函數(shù)中接收應(yīng)用程序的構(gòu)造函數(shù)(因為Application類擴(kuò)展了Context)
viewModel生命周期圖:
ViewModel vs SavedInstanceState
- ViewModels 提供了一種在配置更改時保存數(shù)據(jù)的簡便方式酪术,但是如果應(yīng)用進(jìn)程被操作系統(tǒng)殺死器瘪,那么數(shù)據(jù)則沒有機(jī)會被恢復(fù)。
- 通過 SavedInstanceState 保存的數(shù)據(jù)拼缝,存在于操作系統(tǒng)進(jìn)程的內(nèi)存中娱局。當(dāng)用戶離開應(yīng)用數(shù)個小時之后,應(yīng)用的進(jìn)程很有可能被操作系統(tǒng)殺死咧七,通過 SavedInstanceState 保存的數(shù)據(jù)衰齐,則可以在 Activity 或者 Fragment 重新創(chuàng)建的時候,在其中的 onCreate() 方法中通過 Bundle 恢復(fù)數(shù)據(jù)
因為ViewModel的生命周期是和Activity或Fragment分開的继阻,所以在ViewModel中絕對不能引用任何View對象或者任何引用了Activity的Context的對象耻涛。如果ViewModel中需要Application的Context的話,可以繼承AndroidViewModel瘟檩。
四抹缕、結(jié)語
到這里,相信你已經(jīng)對AAC架構(gòu)有一些初步的了解墨辛,AAC是JetPack中的一部分卓研,JetPack架構(gòu)還包含了很多其他比較實用的組件:
DataBinding:以聲明方式將可觀察數(shù)據(jù)綁定到界面元素;
Navigation:處理應(yīng)用內(nèi)導(dǎo)航所需的一切睹簇,這個組件對于fragment的管理特別有用奏赘;
Paging:逐步從您的數(shù)據(jù)源按需加載信息;
WorkManager:管理您的 Android 后臺作業(yè)太惠;
………………
Google這兩年一直在對這一套的架構(gòu)進(jìn)行不斷的更新磨淌,就是想要解決Android開發(fā)中的很多痛點,以后Architecture Components作為Android開發(fā)的基礎(chǔ)架構(gòu)也是必然的趨勢凿渊。
基于這一點梁只,我們準(zhǔn)備通過一系列的文章去記錄我對JetPack學(xué)習(xí)的要點缚柳。那么我們就從AAC開始吧。