連載内容鎮樓: Android 面試(一):說說 Android 的四種啟動模式 Android 面試(二):如何了解 Activity 的生命周期 Android 面試(三):用廣播 BroadcastReceiver 更新 UI 界面真的好嗎? Android 面試(四):Android Service 你真的能應答自如了嗎? Android 面試(五):探索 Android 的 Handler Android 面試(六):你已經用 SharedPrefrence 的 apply() 替換 commit() 了嗎? Android 面試(七):Serializable 這麼牛逼,Parcelable 要你何用?
寫在前面
面試系列已經相隔很久沒更新了,主要是因為南塵近期搞的「模拟面試」活動花費了太多時間,是以對我的廣大讀者朋友們深表歉意,不過現在開始依然是一有時間就會更新的。畢竟金三銀四,想必想換東家的小夥伴也是比比皆是。
面試場景
什麼是 Activity、View、Window?
Activity 是四大元件之一,也是我們的界面載體,可以展示頁面;而 View 實際上就是一個一個的視圖,這些視圖可以搭載在一個 Layout 檔案上,通過 Activity 的
setContentView()
方法傳遞給 Activity;Window 是一個窗體,每個 Activity 對應一個 Window,通常我們在代碼中用 getWindow() 來擷取它。
你是怎樣了解它們三者之間的關系的?
Activity 像一個工匠 ( 控制單元 ),Window 像窗戶 ( 承載模型 ),View 像窗花( 顯示視圖 ) LayoutInflater 像剪刀,Xml 配置像窗花圖紙。
比喻挺生動,請問可以通俗一點麼?
Activity 下裝了一個 Window,Window 下裝了 View,呃...
正文
這是我在「模拟面試」活動中一個真實的場景,應試者的答案并不能忽悠到我,因為這個答案網上早就傳遍了,但一旦稍微變動一下,應試者的表現就差強人意,很明顯,這位小夥伴沒對源碼進行更加深刻的了解,而隻是簡單地背下了答案。
我們來直接看看實戰中的代碼,相信大家都知道 Activity 通過
setContentView()
方法來加載布局,我們來看看
setContentView()
方法到底是怎樣做的。
實際上是
getWindow().setContentView()
做的處理,那這個
getWindow()
?
你想的沒錯,這個 mWindow 實際上就是 PhoneWindow。Window 是一個抽象類,而 PhoneWindow 實際上就是 Window 的實作繼承類。我們直接看看 PhoneWindow 的
setContentView()
方法,看看會有什麼新發現?
先判斷了
mContentParent
是否為空,這個
mContentParent
是什麼玩意兒?
這個
mContentParent
是一個 ViewGroup 對象,而從注釋中可以明顯地看到 Window 中的内容就放置在這裡。如果為空,則直接執行
installDecor()
,這裡想都不用想都知道是在執行個體這個
mContentParent
,我們可以直接進入源碼來驗證我們的猜想。
這裡代碼挺多,我就不截完了,但邏輯不難,我們先判斷
mDecor
是否為 null,如果是,則直接初始化它。然後判斷
mContentParent
是否為 null,如果是,則直接通過
mDecor
去初始化
mContentParent
。
這塊其實講到這裡大家就差不多了解了,這個問題也就不那麼難答。
每個 Activity 包含了一個 Window 對象,這個對象是由 PhoneWindow 做的實作。而 PhoneWindow 将 DecorView 作為了一個應用視窗的根 View,這個 DecorView 又把螢幕劃分為了兩個區域:一個是 TitleView,一個是 ContentView,而我們平時在 Xml 檔案中寫的布局正好是展示在 ContentView 中的。
用個圖展示一下。