AAC架構(gòu)一:AAC架構(gòu)簡介


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)的問題。

請注意铜靶,您并非擁有 ActivityFragment 的實現(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)圖如下:
image

請注意,每個組件僅依賴于其下一級的組件宰啦。例如苏遥,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活動圖:


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生命周期圖:

image

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開始吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末搪锣,一起剝皮案震驚了整個濱河市秋忙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌构舟,老刑警劉巖翰绊,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異旁壮,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谐檀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門抡谐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人桐猬,你說我怎么就攤上這事麦撵。” “怎么了溃肪?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵免胃,是天一觀的道長。 經(jīng)常有香客問我惫撰,道長羔沙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任厨钻,我火速辦了婚禮扼雏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘夯膀。我一直安慰自己诗充,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布诱建。 她就那樣靜靜地躺著蝴蜓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俺猿。 梳的紋絲不亂的頭發(fā)上茎匠,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機(jī)與錄音辜荠,去河邊找鬼汽抚。 笑死,一個胖子當(dāng)著我的面吹牛伯病,可吹牛的內(nèi)容都是我干的造烁。 我是一名探鬼主播否过,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼惭蟋!你這毒婦竟也來了苗桂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤告组,失蹤者是張志新(化名)和其女友劉穎煤伟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體木缝,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡便锨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了我碟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片放案。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖矫俺,靈堂內(nèi)的尸體忽然破棺而出吱殉,到底是詐尸還是另有隱情,我是刑警寧澤厘托,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布友雳,位于F島的核電站,受9級特大地震影響铅匹,放射性物質(zhì)發(fā)生泄漏押赊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一伊群、第九天 我趴在偏房一處隱蔽的房頂上張望考杉。 院中可真熱鬧,春花似錦舰始、人聲如沸崇棠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枕稀。三九已至,卻和暖如春谜嫉,著一層夾襖步出監(jiān)牢的瞬間萎坷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工沐兰, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留哆档,地道東北人。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓住闯,卻偏偏與公主長得像瓜浸,于是被迫代替她去往敵國和親澳淑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容