在 Activity 中進行一些窗口類的操作時,有時操作 Activity意推,有時操作 Window豆瘫,有時又操作 DecorView,腦子很亂菊值。在這里梳理一下 Activity外驱,Window,DecorView腻窒,ViewRootImpl 之間的關(guān)系昵宇。
Activity 管理生命周期,通過 Window 顯示 View儿子。
Window 負責創(chuàng)建與管理 DecorView瓦哎,通過 WindowManager,使用自己的 WindowManager.LayoutParams mWindowAttributes 顯示自己的 DecorView柔逼。
WindowManagerGlobal 創(chuàng)建 ViewRootImpl蒋譬,ViewRootImpl 負責與 WMS,SF 交互愉适,顯示犯助,更新 View。
PhoneWindow 創(chuàng)建 DecorView:
DecorView 是 Activity 所擁有的 View 樹的頂層 View维咸。它是在 PhoneWindow 的構(gòu)造函數(shù)中創(chuàng)建的剂买。
Activity.setContentView
每次創(chuàng)建 Activity 時都要使用的 setContentView扑媚。其實就是將 View 添加為 DecorView 的 mContentParent ( id ==?Window.ID_ANDROID_CONTENT ) 的子 View。
要獲取這個 mContentParent雷恃,可以使用
getWindow().getDecorView().findViewById(Window.ID_ANDROID_CONTENT)
Window 布局屬性如何生效
Window 內(nèi)部有 WindowManager.LayoutParams? mWindowAttributes 成員變量疆股。
通過 Window 更改的布局屬性,最終就是通過這個 mWindowAttributes 生效的倒槐。
舉個例子旬痹,調(diào)用 Window 的setSoftInputMode:
設(shè)置屬性后,調(diào)用 dispatchWindowAttributesChanged 生效:
對于 Activity 的 PhoneWindow讨越,mCallback 就是 Activity:
最終两残,Activity 通過 WindowManager 更新 LayoutParams:
ViewRootImpl
ViewRootImpl 負責與 WMS,SF 交互把跨。
ViewRootImpl 是在 addView 時人弓,在 WindowManagerGlobal 中創(chuàng)建的。所以着逐,對于 Activity 和 Window崔赌,ViewRootImpl 其實是不可見的:
Window vs PopupWindow
綜上,向 WMS 添加 View耸别,從 app 的角度看健芭,Window 和 DecorView 不是必須的。Window 只是方便對 View 進行管理秀姐,除了 Activity慈迈,也可以在別的地方使用 Window,比如 Dialog 就是通過 Window 添加 View 的省有。
同時痒留,Window 也不是必須的。比如 PopupWindow蠢沿,自己作為 Window伸头,沒有使用到 Window。同時也沒有使用 DecorView搏予,而是使用自己的 PopupDecorView:
PopupWindow 使用 WindowManger 添加 View: