在 Activity 中进行一些窗口类的操作时,有时操作 Activity,有时操作 Window,有时又操作 DecorView,脑子很乱。在这里梳理一下 Activity,Window,DecorView,ViewRootImpl 之间的关系。
Activity 管理生命周期,通过 Window 显示 View。
Window 负责创建与管理 DecorView,通过 WindowManager,使用自己的 WindowManager.LayoutParams mWindowAttributes 显示自己的 DecorView。
WindowManagerGlobal 创建 ViewRootImpl,ViewRootImpl 负责与 WMS,SF 交互,显示,更新 View。
PhoneWindow 创建 DecorView:
DecorView 是 Activity 所拥有的 View 树的顶层 View。它是在 PhoneWindow 的构造函数中创建的。
Activity.setContentView
每次创建 Activity 时都要使用的 setContentView。其实就是将 View 添加为 DecorView 的 mContentParent ( id == Window.ID_ANDROID_CONTENT ) 的子 View。
要获取这个 mContentParent,可以使用
getWindow().getDecorView().findViewById(Window.ID_ANDROID_CONTENT)
Window 布局属性如何生效
Window 内部有 WindowManager.LayoutParams mWindowAttributes 成员变量。
通过 Window 更改的布局属性,最终就是通过这个 mWindowAttributes 生效的。
举个例子,调用 Window 的setSoftInputMode:
设置属性后,调用 dispatchWindowAttributesChanged 生效:
对于 Activity 的 PhoneWindow,mCallback 就是 Activity:
最终,Activity 通过 WindowManager 更新 LayoutParams:
ViewRootImpl
ViewRootImpl 负责与 WMS,SF 交互。
ViewRootImpl 是在 addView 时,在 WindowManagerGlobal 中创建的。所以,对于 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: