Dialog 的显示过程分析

Tip

这篇文章是由设计模式中的 Buidler 模式中引出的,由于 AlertDialog 使用了 builder 模式,在分析 Dialog 的过程中,用到的 WindowManager 来完成到屏幕的展示,如果想了解 Builder 模式的可以看 这里

正文

在 Dialog 的 show 方法的最后,是通过调用 WindowManager 的 addView 方法将视图最后显示到了屏幕上,接下来就深入了解 addView 方法的工作过程

其实,不单是 Dialog ,Activity 、Toast 等需要显示到屏幕上的内容,都是通过 WindowManager 完成的。

WindowManager 在系统注册时会保存 WindowManagerImpl 对象到 ContextImpl 类中的一个静态 Map 中的,使用 Context 的 getSystemService 方法提供单例的对象。

工作过程

第一步 WindowManger 的方法

Dialog 中的 mWindowManager 为 WindowManagerImpl 对象,是全局单例的对象,在 Dialog 的构造函数中初始化 mWindowManager 参数的值,并在 Dialog 的构造函数中创建 Window 对象,Window 对象创建之后,调用其 setWindowManager 方法建立与 WindowManagerImpl 之间的联系

setWindowManager 中主要完成了根据 Window 对象创建新的与 Window 有联系的 WindowManagerImpl 实例的任务,并为 Window 中的属性 mWindowManager 赋值,在 Java 层上 Window 与 WindowManager 建立了第一步联系。

mWindowManger = new WindowManagerImpl(mDisplay,window);

由于 Java 中对象传递为值传递,所以 Dialog 中将 WindowManagerImpl 传递到 Window 对象中进行操作,WindowManagerImpl 对象发生改变,Dialog 中的 WindowManagerImpl 对象也会跟着改变的,所以,在 Dialog 的 show 方法中,最终调用的也是与当前 Window 有关联的 WindowManagerImpl 对象的 addView 方法

注意:这里是使用单例的 WindowManagerImpl ,通过不同的 Window ,构建了与 Window 有关联的 WindowManagerImpl 对象

第二步 WindowManagerGlobal 的方法

在 WindowManagerImpl 中存在一个单例存在的 WindowManagerGlobal 对象,在 WindowManagerImpl 的各个方法中,将任务的执行过程传递到了 WindowManagerGlobal 中,在传递过程中除了将 View、LayoutParams 传递,还将 WindowManagerImpl 中关联的 window 对象也一起传递

在 WindowManagerGlobal 的 addView 方法中,最后通过 ViewRootImpl 的 setView 将 View 显示,具体过程是与 WindowManagerService 的交互

ViewRootImpl

继承自 Handler 类,是作为 native 层和 Java 层 View 系统通信的桥梁

ViewRootImpl 中保存了当前线程,开发过程中在子线程中更新 UI 会抛出异常,是因为 ViewRootImpl 是 UI 线程中创建的,并不是因为只有 UI 线程才可以更新 UI

第三步 建立与 WindowManagerService 的联系

在 ViewRootImpl 的构造方法中,会调用 WindowManagerGlobal 的 getWindowSession 方法获取 IManagerSession 对象

首先 getWindowManagerService 方法中,通过 ServiceManager.getService("window") 方法获得 IBinder 对象,Android Framework 与 WMS 的通信通过 Binder 机制,再通过 IManagerManager 对象的 Stub 类的 asInterface 函数将 IBinder 转换成 IWindowManager 对象,再通过 IManagerManager 的 openSession 方法来与 WMS 建立一个长期的通信会话,需求都通过 Session 来交换信息

简述总结一下这个过程,通过 Binder 机制获取 IManagerSession 对象,再通过 IManagerSession 对象来跟 WMS 完成信息的交换

第四步 ViewRootImpl 的 setView 方法

在 WindowManagerGlobal 的 addView 方法中,调用 ViewRootImpl 的 setView 方法

  1. requestLayout View 树的 measure layout draw 过程

  2. sWindowSession.add() 方法,向 WMS 发起显示当前 Window 的请求

你可能感兴趣的:(Dialog 的显示过程分析)