0%

理解 Window 和 WindowManager(二):Window 的内部机制

1. Window 概述

  • Window 是一个抽象的概念, 每一个 Window 都对应着一个 View 和一个 ViewRootImpl
  • Window 和 View 通过 ViewRootImpl 来建立联系,因此 Window 不是实际存在的,它是以 View 的形式存在,View 才是 Window 存在的实体
  • 在实际使用中无法直接访问 Window,对 Window 的访问必须通过 WindowManager

2. Window 的添加过程

  • 分析源码,Window 的添加过程涉及到的主要的类和接口有 WindowManagerWindowManagerImplWindowManagerGlobalViewRootImplWindowSessionIWindowSessionWindowManagerService

  • 涉及到的涉及模式有桥接模式private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();,将所有的操作全部委托WindowManagerGlobal 来实现,WindowManagerGlobal 以工厂的形式向外提供自己的实例

    • 分析源码,WindowManagerGlobaladdView() 方法主要的步骤

      1. 检查参数是否合法,如果是子 Window 那么还需要调整一些布局参数
      2. 创建 ViewRootImpl 并将 View 添加到列表中
      3. 通过 ViewRootImpl 来更新界面并完成 Window 的添加过程
    • 结论:底层通过 Binder 对象完成添加过程,所以 Window 的添加过程是一次 IPC 调用

  • 通过逐级调用,Window 的添加请求就交给 WindowManagerService 处理,在 WindowManagerService 内部会为每一个应用保留一个单独的 Session

3. Window 的删除过程

  • 分析源码,Window 的删除过和添加过程一样,都是先通过 WindowManagerImpl 后,再进一步通过 WindowManagerGlobal 来实现
  • 在 WindowManager 中提供了两种删除接口 removeView()removeViewImmediate(),分别表示异步删除同步删除(较少使用)
  • 真正删除 View 的逻辑在 dispatchDetachedFromWindow() 方法的内部实现,该方法主要做了四件事:
    1. 垃圾回收相关的工作,比如清楚数据和消息、移除回调
    2. 通过 Session 的 remove() 方法删除 Window: mWindowSession.remove(mWindow);Window 的删除同样是一个 IPC 过程,最终会调用 WindowManagerService 的 removeWindow() 方法
    3. 调用 View 的 dispatchDetachedFromWindow() 方法,在内部会调用 View 的 onDetachedFromWindow()onDetachedFromWindowInternal() 方法。对于 onDetachedFromWindow() 方法,当 View 从 Window 中移除时,该方法会被调用,可以在这个方法内部做一些资源回收的工作,比如终止动画、停止线程等
    4. 调用 WindowManagerGlobal 的 doRemoveView() 方法刷新数据,包括 mRootsmParamsmDyingViews,需要将当前 Window 所关联的这三类对象从列表中删除

4. Window 的更新过程

  • 分析源码,Window 的更新过程其实现是在 WindowManagerGlobalupdateViewLayout() 方法
  • updateViewLayout() 方法主要的逻辑:
    1. 首先它需要更新 View 的 LayoutParams 并替换掉老的 LayoutParams,接着再更新 ViewRootImpl 中的 LayoutParams,这一步是通过 ViewRootImpl 的 setLayoutParams() 方法实现的
    2. 在 ViewRootImple 中会通过 scheduleTraversals() 方法来对 View 重新布局,包括测量、布局、绘制这三个过程
    3. 除了 View 本身的重绘之外,ViewRootImpl 还会通过 WindowSession 来更新 Window 的视图,这个过程最终是由 WindowManagerService 的 relayoutWindow() 方法实现,Window 的更新同样是一个 IPC 过程
-------------------- 本文结束感谢您的阅读 --------------------