連載內(nèi)容鎮(zhèn)樓:
Android 面試(一):說說 Android 的四種啟動模式
Android 面試(二):如何理解 Activity 的生命周期
Android 面試(三):用廣播 BroadcastReceiver 更新 UI 界面真的好嗎台颠?
Android 面試(四):Android Service 你真的能應(yīng)答自如了嗎?
Android 面試(五):探索 Android 的 Handler
Android 面試(六):你已經(jīng)用 SharedPrefrence 的 apply() 替換 commit() 了嗎勒庄?
Android 面試(七):Serializable 這么牛逼串前,Parcelable 要你何用?
寫在前面
面試系列已經(jīng)相隔很久沒更新了实蔽,主要是因為南塵近期搞的「模擬面試」活動花費了太多時間荡碾,所以對我的廣大讀者朋友們深表歉意,不過現(xiàn)在開始依然是一有時間就會更新的局装。畢竟金三銀四坛吁,想必想換東家的小伙伴也是比比皆是。
面試場景
什么是 Activity铐尚、View拨脉、Window?
Activity 是四大組件之一,也是我們的界面載體宣增,可以展示頁面玫膀;而 View 實際上就是一個一個的視圖,這些視圖可以搭載在一個 Layout 文件上爹脾,通過 Activity 的 setContentView()
方法傳遞給 Activity匆骗;Window 是一個窗體劳景,每個 Activity 對應(yīng)一個 Window,通常我們在代碼中用 getWindow() 來獲取它碉就。
你是怎樣理解它們?nèi)咧g的關(guān)系的盟广?
Activity 像一個工匠 ( 控制單元 ),Window 像窗戶 ( 承載模型 )瓮钥,View 像窗花( 顯示視圖 ) LayoutInflater 像剪刀筋量,Xml 配置像窗花圖紙。
比喻挺生動碉熄,請問可以通俗一點么桨武?
Activity 下裝了一個 Window,Window 下裝了 View锈津,呃...
正文
這是我在「模擬面試」活動中一個真實的場景呀酸,應(yīng)試者的答案并不能忽悠到我,因為這個答案網(wǎng)上早就傳遍了琼梆,但一旦稍微變動一下性誉,應(yīng)試者的表現(xiàn)就差強(qiáng)人意,很明顯茎杂,這位小伙伴沒對源碼進(jìn)行更加深刻的理解错览,而只是簡單地背下了答案。
我們來直接看看實戰(zhàn)中的代碼煌往,相信大家都知道 Activity 通過 setContentView()
方法來加載布局倾哺,我們來看看 setContentView()
方法到底是怎樣做的。
實際上是 getWindow().setContentView()
做的處理刽脖,那這個 getWindow()
羞海?
你想的沒錯,這個 mWindow 實際上就是 PhoneWindow曲管。Window 是一個抽象類却邓,而 PhoneWindow 實際上就是 Window 的實現(xiàn)繼承類。我們直接看看 PhoneWindow 的 setContentView()
方法翘地,看看會有什么新發(fā)現(xiàn)?
先判斷了 mContentParent
是否為空癌幕,這個 mContentParent
是什么玩意兒衙耕?
這個 mContentParent
是一個 ViewGroup 對象,而從注釋中可以明顯地看到 Window 中的內(nèi)容就放置在這里勺远。如果為空橙喘,則直接執(zhí)行 installDecor()
,這里想都不用想都知道是在實例這個 mContentParent
胶逢,我們可以直接進(jìn)入源碼來驗證我們的猜想厅瞎。
這里代碼挺多饰潜,我就不截完了,但邏輯不難和簸,我們先判斷 mDecor
是否為 null彭雾,如果是,則直接初始化它锁保。然后判斷 mContentParent
是否為 null薯酝,如果是,則直接通過 mDecor
去初始化 mContentParent
爽柒。
這塊其實講到這里大家就差不多了解了吴菠,這個問題也就不那么難答。
每個 Activity 包含了一個 Window 對象浩村,這個對象是由 PhoneWindow 做的實現(xiàn)做葵。而 PhoneWindow 將 DecorView 作為了一個應(yīng)用窗口的根 View,這個 DecorView 又把屏幕劃分為了兩個區(qū)域:一個是 TitleView心墅,一個是 ContentView酿矢,而我們平時在 Xml 文件中寫的布局正好是展示在 ContentView 中的。
用個圖展示一下嗓化。