Android面試集錦系列(30)——自定義View的狀態是如何儲存的?
2009年冬天,北京寒風刺骨,我們公司組織到北京進行為期一週的Android開發培訓,講師來自荷蘭的Hello9培訓機構。讓我印向深刻的是,說著極易讓人打瞌睡的北歐英文的講師,在給我們講EditText控制元件時,說到在Activity轉屏時EditText是不會儲存狀態的(即在EditText中輸入字元,然後轉屏,重建Activity後EditText之前輸入的字元沒有被儲存)。為表示他的正確,他特意演示了一下,這一演示發現狀態被儲存了!後來他解釋說是,在早期的SDK版本(1.6以前)確實是不會儲存的,之後Android做了改進。
在我問面試者關於自定義View的問題時,常常會問他們關於儲存View的狀態的問題,如果對方不大清楚怎麼做,我會認為面試者在自己定View上的經驗不夠,因為至少要知道可以在View的onSaveInstanceState中儲存資料吧。
面試題:自定義View的狀態是如何儲存的?
Android有一套標準的做法,做過自定義View的人很容易遇到這個問題,因為Activity轉屏,或Home鍵到後臺很容易在被系統銷燬,恢復時我們肯定是希望看到View保持之前狀態。
提示:系統記憶體緊張時會主動銷燬這類Activity,做為開發我們可以利用DDMS的stop process模擬這一動作而不必等到記憶體緊張時,如下圖所示:

這個標準的做法可以隨便從一個Android自帶的控制元件中看到,如TextView的原始碼( SavedState extends BaseSavedState )。
/** * User interface state that is stored by TextView for implementing * {@link View#onSaveInstanceState}. */ public static class SavedState extends BaseSavedState { int selStart; int selEnd; CharSequence text; boolean frozenWithFocus; CharSequence error; SavedState(Parcelable superState) { super(superState); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeInt(selStart); out.writeInt(selEnd); out.writeInt(frozenWithFocus ? 1 : 0); ......
BaseSavedState是View的一個內部靜態類,從程式碼上我們也很容易看出是把控制元件的屬性(如selStart)打包到Parcel容器,Activity的onSaveInstanceState、onRestoreInstanceState最終也會呼叫到控制元件的這兩個同名方法。
Parcel相關的問題以後專門再講,現在我們可以焦點先放在狀態儲存上,先看一下Activity的狀態如何儲存的:

注:無法保證系統會在銷燬Activity前一定呼叫onSaveInstanceState,例如使用者使用“返回” 按退出 Activity 時,因為使用者的行為是在顯式關閉 Activity,所以不會呼叫onSaveInstanceState。
如果系統呼叫onSaveInstanceState,那麼它是在onStop還是在onPause之前執行呢?
可以肯定的是它會在呼叫 onStop之前,但是是不是在onPuase之前就不能確認了,要看情況,官方文件在說明這個執行順序時用了“可能”這個詞。
小結
Activity類的onSaveInstanceState預設實現會恢復Activity的狀態,預設實現會為佈局中的每個View呼叫相應的 onSaveInstanceState方法,讓每個View都能儲存自身的資訊。
這裡需要注意一個細節:想要儲存View的狀態,需要在XML佈局檔案中提供一個唯一的ID(android:id),如果沒有設定這個ID的話,View控制元件的onSaveInstanceState是不會被呼叫的。
最後
在現在這個金三銀四的面試季,我自己在網上也蒐集了很多資料做成了文件和架構視訊資料免費分享給大家【 包括高階UI、效能優化、架構師課程、NDK、Kotlin、混合式開發(ReactNative+Weex)、Flutter等架構技術資料 】,希望能幫助到您面試前的複習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習。
資料獲取方式:加入Android架構交流QQ群聊:513088520 ,進群即領取資料!!!
點選連結加入群聊【Android移動架構總群】:加入群聊

資料大全