1. Window 概述
- Window 是一个抽象的概念, 每一个 Window 都对应着一个 View 和一个 ViewRootImpl
- Window 和 View 通过 ViewRootImpl 来建立联系,因此 Window 不是实际存在的,它是以 View 的形式存在,View 才是 Window 存在的实体
- 在实际使用中无法直接访问 Window,对 Window 的访问必须通过 WindowManager
2. Window 的添加过程
分析源码,Window 的添加过程涉及到的主要的类和接口有
WindowManager
、WindowManagerImpl
、WindowManagerGlobal
、ViewRootImpl
、WindowSession
、IWindowSession
、WindowManagerService
等涉及到的涉及模式有桥接模式:
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
,将所有的操作全部委托给WindowManagerGlobal
来实现,WindowManagerGlobal
以工厂的形式向外提供自己的实例分析源码,
WindowManagerGlobal
的addView()
方法主要的步骤- 检查参数是否合法,如果是子 Window 那么还需要调整一些布局参数
- 创建 ViewRootImpl 并将 View 添加到列表中
- 通过 ViewRootImpl 来更新界面并完成 Window 的添加过程
结论:底层通过 Binder 对象完成添加过程,所以 Window 的添加过程是一次 IPC 调用
通过逐级调用,Window 的添加请求就交给 WindowManagerService 处理,在 WindowManagerService 内部会为每一个应用保留一个单独的 Session
3. Window 的删除过程
- 分析源码,Window 的删除过和添加过程一样,都是先通过 WindowManagerImpl 后,再进一步通过 WindowManagerGlobal 来实现
- 在 WindowManager 中提供了两种删除接口
removeView()
和removeViewImmediate()
,分别表示异步删除和同步删除(较少使用) - 真正删除 View 的逻辑在
dispatchDetachedFromWindow()
方法的内部实现,该方法主要做了四件事:- 垃圾回收相关的工作,比如清楚数据和消息、移除回调
- 通过 Session 的
remove()
方法删除 Window:mWindowSession.remove(mWindow);
,Window 的删除同样是一个 IPC 过程,最终会调用 WindowManagerService 的removeWindow()
方法 - 调用 View 的
dispatchDetachedFromWindow()
方法,在内部会调用 View 的onDetachedFromWindow()
和onDetachedFromWindowInternal()
方法。对于onDetachedFromWindow()
方法,当 View 从 Window 中移除时,该方法会被调用,可以在这个方法内部做一些资源回收的工作,比如终止动画、停止线程等 - 调用 WindowManagerGlobal 的
doRemoveView()
方法刷新数据,包括mRoots
、mParams
和mDyingViews
,需要将当前 Window 所关联的这三类对象从列表中删除
4. Window 的更新过程
- 分析源码,Window 的更新过程其实现是在 WindowManagerGlobal 的
updateViewLayout()
方法 updateViewLayout()
方法主要的逻辑:- 首先它需要更新 View 的 LayoutParams 并替换掉老的 LayoutParams,接着再更新 ViewRootImpl 中的 LayoutParams,这一步是通过 ViewRootImpl 的
setLayoutParams()
方法实现的 - 在 ViewRootImple 中会通过
scheduleTraversals()
方法来对 View 重新布局,包括测量、布局、绘制这三个过程 - 除了 View 本身的重绘之外,ViewRootImpl 还会通过 WindowSession 来更新 Window 的视图,这个过程最终是由 WindowManagerService 的
relayoutWindow()
方法实现,Window 的更新同样是一个 IPC 过程
- 首先它需要更新 View 的 LayoutParams 并替换掉老的 LayoutParams,接着再更新 ViewRootImpl 中的 LayoutParams,这一步是通过 ViewRootImpl 的