7.1 Window、WindowManager和WMS
- Window是一个抽象类,具体的实现类为PhoneWindow,它对View进行管理。
- WindowManager 是一个接口类,继承自接口ViewManager,它是用来管理Window的,它的实现类为WindowManagerImpl。如果我们]想要对Window (View)进行添加、更新和删除操作就可以使用WindowManager,。
- WindowManager 会将具体的工作交由WMS来处理,WindowManager 和WMS通过Binder来进行跨进程通信,WMS作为系统服务有很多API是不会暴露给WindowManager的,这一点与ActivityManager和AMS的关系有些类似。
Window包含了View并对View进行管理,Window用虚线来表示是因为Window是一个抽象概念,用来描述一个窗口,并不是真实存在的,Window 的实体其实也是View。WindowManager用来管理Window,而WindowManager所提供的功能最终会由WMS进行处理。
7.2 WindowManager的关联类
7.3 Window的属性
7.3.1 Window的类型和显示次序
Window的类型总体来说分为三大类:
- Application Window(应用程序窗口)
- Sub Window(子窗口)
- System Window(系统窗口)
应用程序窗口
public static final int FIRST_APPLICATION_WINDOW = 1;//1
public static final int TYPE_BASE_APPLICATION = 1;//窗口的基础值,其他的窗口值要大于这个值
public static final int TYPE_APPLICATION = 2;//普通的应用程序窗口类型
public static final int TYPE_APPLICATION_STARTING = 3;//应用程序启动窗口类型,用于系统在应用程序窗口启动前显示的窗口。
public static final int TYPE_DRAWN_APPLICATION = 4;
public static final int LAST_APPLICATION_WINDOW = 99;//2
应用程序窗口的Type值范围为1到99。
子窗口
子窗口,不能独立的存在,需要附着在其他窗口才可以,PopupWindow就属于子窗口。子窗口的Type值范围为1000到1999。
系统窗口
Toast、输入法窗口、系统音量条窗口、系统错误窗口都属于系统窗口。系统窗口的类型定义如下所示:系统窗口的类型值有接近40个,这里只列出了一小部分, 系统窗口的Type值范围为2000到2999。
窗口显示次序
当一个进程向WMS申请一个窗口时,WMS会为窗口确定显示次序。为了方便窗口显示次序的管理,手机屏幕可以虚拟的用X、Y、Z轴来表示,其中Z轴垂直于屏幕,从屏幕内指向屏幕外,这样确定窗口显示次序也就是确定窗口在Z轴上的次序,这个次序称为Z-Oder。Type值是Z-Oder排序的依据,我们知道应用程序窗口的Type值范围为1到99,子窗口1000到1999 ,系统窗口 2000到2999,,一般情况下,Type值越大则Z-Oder排序越靠前,就越靠近用户。
7.3.2 Window的标志
Window的标志也就是Flag,用于控制Window的显示,同样被定义在WindowManager的内部类LayoutParams中。
设置Window的Flag有三种方法:
- 第一种是通过Window的addFlags方法;
- 第二种通过Window的setFlags方法;
- 第三种则是给LayoutParams设置Flag,并通过WindowManager的addView方法进行添加。
7.3.3 软键盘相关模式
为了使得软键盘窗口能够按照期望来显示,WindowManager的静态内部类LayoutParams中定义了软键盘相关模式:
设置SoftInputMode:
- AndroidManifest中Activity的属性android:windowSoftInputMode;
- Java代码
getWindow().setSoftInputMode
。
7.4 Window的操作
对于Window的操作,最终都是交由WMS来进行处理。窗口的操作分为两大部分,一部分是WindowManager处理部分,另一部分是WMS处理部分。
7.4.1 系统窗口的添加过程
7.4.2 Activity的添加过程
- Activity 在启动过程中,如果Activity所在的进程不存在则会创建新的进程,创建新的进程之后就会运行代表主线程的实例ActivityThread;
- 当界面要与用户进行交互时,会调用ActivityThread 的handleResumeActivity方法;
- performResumeActivity方法最终会调用Activity 的onResume方法;
- 得到ViewManager类型的对象后,调用了ViewManager 的addView方法,而addView方法则是在WindowManagerImpl中实现的,addView方法的第一个参数为DecorView。
7.4.3 Window的更新过程
Window的更新过程和Window的添加过程是类似的。
- 调用ViewManager的updateViewLayout方法,updateViewLayout 方法在WindowManagerImpl 中实现,WindowManagerImpl的updateViewLayout方法会调用WindowManagerGlobal的updateViewI ayout方法
- 更新的参数设置到View中,得到要更新的窗口在View列表中的索引在ViewRootImpl列表中根据索引得到窗口的ViewRootlmpl,更新布局参数列表,调用ViewRootImpl的setLayoutParams方法将更新的参数设置到ViewRootImpl 中,ViewRootImpl的setLayoutParams 方法在最后会调用ViewRootImpl的scheduleTraversals方法。
- 在TraversalRunnable的run方法中调用了doTraversal方法,在doTraversal方法中又调用了performTraversals 方法,performTraversals 方法使得ViewTree开始View的工作流程:
- relayoutWindow方法内部会调用IWindowSession 的relayout方法来更新Window视图,最终会调用WMS的relayoutWindow方法。
- performTraversals 方法分别调用performMeasure、performLayout和performDraw方法,它们的内部又会调用View的measure、layout和draw方法,这样就完成了View 的工作流程。
- 在performTraversals方法中更新了Window视图,又执行Window中的View的工作流程,这样就完成了Window 的更新。