Window
1 window介绍
Android中window是由WindowManagerService(WMS)管理,包括增加和删除窗口,确定窗口的大小和位置,以及实现窗口的切换,窗口的动画等功能。从WMS的角度来看,一个窗口并不是Window类,而是一个View类。Wms收到用户消息后,需要把消息派发给窗口,View本身并不能直接接收Wms传递过来的消息,真正接收用户消息的必须是IWindow类,而实现IWindow类的是ViewRoot.W类,每一个W内部都包含一个View变量。
2 窗口的类型
2.1 应用窗口 它一般指该窗口对一个Activity,由于加载Activity是由Ams完成的,因此对于应用程序来讲,要创建一个应用窗口,只能在Activity内部完成。
2.2 子窗口 它必须有一个父窗口,父窗口可以是一个应用窗口类型,也可以是任何其他类型的窗口。
2.3 系统窗口 一般由系统进程创建系统窗口。
WindowManager类对这三种类型进行细化,把每一种类型都用一个int常量表示,这实际代表窗口对应的层(Layer).Wms进行窗口叠加时,会按照int常量的大小分配不同层,int值越大,代表层的位置越靠上面,即所谓Z-order。 Activity的层值一般不会大于99,创建子窗口时,客户端可以指定窗口类型介于1000~1999,Wms可以动态调整层值。创建系统窗口时,可以指定层值在2000~2999之间,注意:有的系统窗口只能出现一个,Wms在接收到创建窗口的消息时,会进行检查,确保该窗口只能被创建一次。
3 token变量的含义
我们在看源码的过程中,很多地方都出现了token,它出现的含义是什么?token在英语中的含义为象征,符号,代表。在创建窗口时,其类型一般是一个IBinder对象,作用即为了进行IPC调用。与创建窗口的相关的IPC对象有两个,一个是指向某个W类的token,另一个是指向 某个HistoryRecord的token,HistoryRecord对象是Ams内部为运行的每一个Activity创建的一个Binder对象,客户端的Activity可以通过该Binder对象通知Ams当前运行的Activity的状态。从Android2.3后,HistoryRecord改为ActivityRecord。
3.1 token相关源码的位置如下:
位置 定义
Activity IBinder mToken
Window IBinder mAppToken
WindowManager.LayoutParams IBinder token
ViewRoot View.AttachInfo mAttachInfo;
View View.AttachInfo mAttachInfo;
View.AttachInfo IBinder mWindowToken;
IBinder mPanelParentWindowToken;
IWindow mWindow;
3.2 token初始化时机
Ams内部为每一个运行的Activity都创建了一个ActivityRecord对象,该对象的基类是一个Binder,因此mToken变量的意义正是指向了ActivityRecord类,该变量的值是在Activity.init()函数完成的。
Window中的mAppToken:每一个Window对象都有一个mAppToken变量,注意 这里说的是Window对象,而不是窗口,一个窗口的本质是一个View,而Window类只是一个应用窗口的抽象,注意:Window侧重表达一个对应的Activity的窗口,而窗口(View)则侧重于任意视图窗口的显示。所以,AppToken并不是W类的引用,而是Ams在远程为每一个Activity创建的HistoryRecord的引用。注意:Window并不一定要对应一个Activity,Dialog类中也会包含一个Window对象,因此,如果Window类不属于某个Activity,则mAppToken为空,否则它与Activity中的mToken值相同。
WindowManager.LayoutParams中的token,WindowManager类用于向Ams中添加一个窗口,而token是指定该窗口对应的Binder对象,以便于Wms通过该Binder对象对该窗口进行IPC调用。其中Binder对象应该是谁?该token应该是W(ViewRootImp.W)类。该token变量的值可以分三种: 如果创建的窗口是应用窗口,token的起始赋值是mAppToken(Window中),而进行添加操作时,源码中会对token进行修正,并最终转换为指向一个W(ViewRootImp.W)对象。 如果创建的窗口为子窗口,token为其父窗口的W对象。 如果创建的窗口是系统窗口,那么,token值为空。