天天看點

Android 面試(八):說說 Activity、View、Window 之間的關系吧

連載内容鎮樓: 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 中的。

用個圖展示一下。

繼續閱讀