番外 - Activity, DecorView, Window, ViewRootImpl, WindowManager 之间的关系

Android ViewRoot&DecorView&Window&Activity关系
DecorView介绍
Activity、View、Window的理解一篇文章就够了
Android - Activity 与 Window 与 View 之间的关系

Window

  • Window 表示一个窗口的概念, 是一个抽象类, 具体实现是 PhoneWindow. 每一个 Window 都对应着一个 View 和一个 ViewRootImpl. WindowView 通过 ViewRootImpl 来建立联系, 因此 Window 并不是实际存在的, 它是以 View 的形式存在. 这点可以从 WindowManager 内定义的接口方法可以看出, 都是针对View 的, 这说明 View 才是 Window 存在的实体. Android 中所有的视图都是通过 Window 来呈现的, 不管是 Activity, Dialog 还是 Toast, 它们的视图实际上都是附加在 Window 上的. 因此也可以说 Window 实际是 View 的直接管理者.
     

 

WindowManager

  • WindowManager 是外界访问 Window 的唯一入口, 并且可以通过 WindowManager 来创建一个 Window, WindowManager 是一个接口, 它真正实现是 WindowManagerImpl, 但是又将内部的三大操作交给了 WindowManagerGlobal 来处理. 所以最终就是调用 WindowManagerGlobal.addView() 来创建. addView 的过程其实就是创建 Window 的过程. 在 addView 中 通过调用 ViewRootImpl 来更新界面并完成 Window 的添加. (其实最终 Window 的添加请求是交给 WindowManagerService 去处理了. WindowManagerService 内部会为每一个应用保留一个单独的 Session )
  • WindowManagerWindowManagerService 的交互是一个 IPC 的过程.
     

 

Activity 的 Window 创建过程

  • ActivityThread.performLaunchActivity() 方法中会调用 Activity.attach(...) 方法为其关联运行过程中所依赖的一系列上下文环境变量.
  • Activity.attach(...) 中, 系统会创建 Activity 所属的 Window 对象并为其设置回调接口, Window 对象的创建是通过 PolicyManagermakeNewWindow 方法实现的.
  • 由于 Activity 实现了 WindowCallback 接口, 因此当 Window 接收到外界的状态改变时就会回调 Activity 的方法. Callback 接口中的方法很多, 有几个是我们非常熟悉的, 例如: dispatchTouchEvent(), onAttachedToWindow(), onDetachedFromWindow() 等等.
     

 

getWindowManager().addView() 和 addContentView() 的区别

  • Activity 通过 getWindowManager().addView(),最终会调用到 WindowManagerGlobal.addView(),这时会创建一个新的 ViewRootImpl 对象,和原来的 DecoView 不在一条 View 链上,所以它们之间的任何一个调用 requestLayout() 都不会影响到另一个。而 addContentView() 是直接将 view 添加到 DecoView 中,会使 ViewRootImpl 链下的所有 View 重绘。
     

 

Dialog 和 PopupWindow 的区别

  • Dialog 在创建时会新建一个 Window(PhoneWindow),同时也会使用 DecoView 作为这个 PhoneWindow 的根 View,相当于走了一遍 Activity 里创建 PhoneWindowDecoView 的流程。而调用 Dialog.show() 方法,类似于 ActivityThread.performResumeActivity(),将 DecoView 添加到 Window,同时创建 DecoView 链的 RootViewImpl 来管理 DecoView
  • PopupWindow 就和上面 getWindowManager().addView() 类似了,只是创建一条新的 View 链和 ViewRootImpl,并没有创建新的 Window
  • Dialog 通过非 ActivityContext,如 ApplicationService 创建,这是因为 Dialog 通过传入的 Context 来得到 context 里的 mWindowManager (也就是 WindowManagerImpl) 与 mToken,这是为了表明 Dialog 所属的 Activity。在 Window.addView() 时,需要这个 mToken(IBinder 对象),而 ApplicationService 传入的情况下 Tokennull
     

 

一个 Activity 有多少个 ViewRootImpl

  • 每个 ActivityViewRootImpl 数量取决于调用 mWindowManager.addView() 的次数。
    摘自 Framework篇 - 一文搞懂 Activity、View、Window、ViewRootImpl
     

 

你可能感兴趣的:(番外 - Activity, DecorView, Window, ViewRootImpl, WindowManager 之间的关系)