很抱歉上週我由於沉迷代碼而忘了發文。android
今天和你們分享的這篇,本來是《重學安卓》付費專欄連載的第三篇,沒想到在我這幾天業餘時間獨立開發的小應用《JDGD》中,連續趕上了 7 處 「狀態重建」 的場景!網絡
考慮到我在 <掘金> 等熱門技術社區 發文的目標是,提供 「從 0 到 1」、易於理解和貫通的 擺渡文,致力於爲讀者撥開迷霧、創建感性認識。數據結構
於是 原味的、硬核的、鑽研細節的 文章,我可能是在小衆的付費技術社區發佈。對此感興趣的朋友請不要慌,文末連接給出 😉源碼分析
JDGD 的頁面結構是,最外層由一個 Activity 裝載着一個 ContainerFragment,而後 ContainerFragment 中又裝載了 3 個 ChildFragment。至關因而個 3 層嵌套頁面結構。佈局
用戶平時能夠操做的,就是在這 3 個 ChildFragment 之間來回切換。而且當發生旋轉屏幕時,來自 3 個層次的 5 個頁面都會發生重建。設計
這要是換作之前的話,我八成是會被難住,由於我司的產品,手機端是固定豎屏,平板端是固定橫屏,即便開啓了旋轉屏幕模式,也不會走重建的流程,於是多年來我都沒有鑽研過這個問題。3d
而且,網絡上關於重建的文章 可能是人云亦云、含糊不清,並無把最關鍵的細節給講明白、講透,致使我最開始也在 半吊子文章中 白費很多時間。cdn
好在上上星期,我親自覆盤和實證了 「狀態重建」 的知識點,因而這回趕上的幾個問題,都是輕輕鬆鬆地獲得化解 😉。blog
考慮到頁面重建和狀態管理,真的是每一個人都必然會遇到的問題,因而我就 破例 地將 Activity 狀態重建的知識,無保留地分享給你們。繼承
已經付費的小夥伴們請不要擔憂,今天僅僅是經過介紹 Activity 的重建,來奠基對重建的認知基礎,真正的好戲還在後頭 ~
還沒閱讀過的小夥伴也不要着急,正因爲今天講的是基礎,即便只看這篇,你也沒有白來!
很高興見到你!
上一期,我在發表的 《重學安卓:Activity 生命週期的 3 個闢謠》 中,經過介紹網上 99% 的文章都未曾解析過的 「進程模式」,來幫助你們深刻理解 Activity 生命週期 的設計依據、存在乎義 及 注意事項。
而且,文末我還針對網文的 3 個訛傳,來給你們闢了謠。
相信通過這樣一次介紹,你對生命週期擁有了相比其餘人更加深入的認識。😉
那麼這一期,咱們來結合現實的案例,來說解一下 Activity 的重建機制。
就在上週五,我司向客戶推送了 App 新版本,原覺得萬事大吉,畢竟通過了一週的打磨,各項功能都已趨於流暢穩定,沒想到,在客戶近乎變態的數據操做下,有客戶反映 「頁面切換巨卡」、「速度巨慢」。
爲什麼會產生這種狀況呢?我找到編寫該頁面的同事詢問了原因。
同事說,問題在於每次 onPause 時,爲了不App 切到後臺被系統回收致使數據丟失,而作了大量的數據持久化操做。
那爲何不直接經過 Activity 的狀態管理機制 來管理臨時數據呢?
同事說,那東西「不靠譜」,用着感受內心沒底。
…… 是網上介紹 Activity 重建流程和狀態管理的文章不夠多嗎?不是的,網文都有提到:當發生重建時,就會走 onSaveInstanceState 和 onRestoreInstanceState,
然而卻沒有一篇深刻地探究過:當走 onSaveInstanceState 和 onRestoreInstanceState 時,過程當中究竟經歷了哪些細節、背後 決定狀態被成功保存和恢復的關鍵條件 究竟是怎樣的。
這使得讀者在使用這個機制時忐忑不安,沒法 100% 肯定不會出事。
因而在通過源碼分析和再三的實測檢驗後,我將 「重建機制」 及 「狀態管理機制」 的內容整理成這篇文章。
若是閱讀完本文後,你對兩者的緣起、規律有了明確的認識,從而 100% 放心地在往後工做中使用,那個人這番功夫就沒白費 ~
正常的生命週期流程,是頁面從正常建立到銷燬全流程。
而重建流程,則是在特定條件下,引起頁面被銷燬,並再次被建立的流程。
一般是 「系統資源的回收」 或 「配置發生變化」 致使的重建。
劃重點 👆 👆 👆
系統資源回收是指:
當 App 處於背景模式時,可能因系統內存不足而被回收。
例如按下 Home 鍵切回桌面,或是接電話跳轉到電話程序,都有可能使此前的這個 App 處於背景模式。
配置發生變化是指:
當系統配置發生變化時,好比屏幕方向、語言的改變。
一來: 對於資源回收的狀況,保存狀態並等到使用時再恢復,要比後臺存留進程 所佔的資源要小得多。
二來: 對於配置變化的狀況,好比當屏幕方向發生變化時,惟有重建,纔有機會加載不一樣的視圖,若是橫豎屏的佈局不一樣的話。
首先,「狀態」 是指支撐 UI 界面內容展現的臨時數據。
好比 EditText 中的文本、CheckBox 的勾選與否。
有且只有引起重建時,Activity 會走 onSaveInstanceState 和 onRestoreInstanceState,來保存和恢復狀態。
onSaveInstanceState 執行在 onStop 以前,onRestoreInstanceState 執行在 onStart 以後。
其次,Activity 有兩個數據結構用於保存狀態:
一個是 View States,專門用於存儲 View 的狀態;
再一個是 Instance States,用於存儲 View States 以及 開發者在 onSaveInstanceState 中手動保存的 Activity 成員變量。
在引起重建時,Activity 會自動爲咱們保存和恢復 View 的狀態。具體表現爲:
Activity 在 onSaveInstanceState 時,會 自動收集 View Hierachy 中每個 「實現了狀態保存和恢復方法」 的 View 的狀態,這些狀態數據會在 onRestoreInstanceState 時回傳給每個 View。而且回傳時是依據 View 的 id 來逐一匹配的。
劃重點 👆 👆 👆
其中,View 的狀態數據會被收集到 View States 中,View States 也會隨着 Activity 中其餘被指定收集的成員變量,一同被收集到 Instance States 中,等待恢復時逐個恢復。
簡言之:
1.爲了成功保存狀態,要求在 View 內部實現狀態保存和恢復方法。
原生的 View 都有作到;若是是自定義 View,務必記住這一點;若是第三方 View 沒作到,能夠經過繼承其來實現保存和恢復方法。
2.爲了成功恢復狀態,要求在佈局中給 View 賦予相應的 id。
劃重點 👆 👆 👆
3.若是是 Activity 的成員變量,須要額外在 Activity(子類)中重寫 onSaveInstanceState 和 onRestoreInstanceState 方法。
注意:
Activity 中重寫僅僅是爲了額外地保存成員變量。重寫方法時,記得要保留基類(super)的實現,Activity 正是在基類中完成 View 狀態的保存和恢復。
劃重點 👆 👆 👆
在清單文件中爲該 Activity 配置 android:configChanges 屬性。
好比屬性值 orientation|screenSize 對應着旋轉屏幕,locale 對應着語言變化。
如此,在配置發生變化時,不會致使重建,而是走 onConfigurationChanged 回調。
只要遵循 《狀態保存和恢復的的注意事項》一節所提到的關鍵細節,就能穩妥地保存和恢復狀態。
你不再用爲了臨時數據而在 onPause 或 onStop 中執行重量級的持久化存儲操做啦!
看不過癮?這裏只爲你 而準備了一份 簡潔有力的 《重學安卓》認知地圖 😉