注:以下内容基于Android API Version 27(Android 8.1)Linux Kernel 3.18.0
概括
Activity、Dialog、PopupWindow和Toast代表着四种典型Window形式。
-
Activity的Window类型是TYPE_APPLICATION,在WMS有一个唯一的AppWindowToken与之对应。 -
Dialog的Window类型也是TYPE_APPLICATION(Dialog不是子窗口),Dialog和其所在的Activity共用一个AppWindowToken。 -
PopupWindow的Window类型是TYPE_APPLICATION_PANEL,TYPE_APPLICATION_PANEL是子窗口的一种,PopupWindow和其所在的Activity共用一个AppWindowToken。 -
Toast的Window类型是TYPE_TOAST,TYPE_TOAST是系统窗口的一种,Toast的token是由NotificationManagerService创建的,每个Toast对应一个自己的token,Toast的token在WMS对应的是WindowToken。
PhoneWindow/DecorView/ViewRootImpl
PhoneWindow包含一个DecorView。
Activity的content view是DecorView的一个子View,DecorView是content view套用模板(窗口样式)后的根View。
一个DecorView对应一个ViewRootImpl,ViewRootImpl是一个虚拟的根View,本身不是View,ViewRootImpl负责处理View tree 发生的更新请求,同时肩负着与WMS通信和输入事件的派发。
Activity和Dialog都对应一个PhoneWindow对象。PopupWindow和Toast没有对应的PhoneWindow,Activity/Dialog由于有PhoneWindow因此就有了DecorView,DecorView可以通过Window.Callback将输入事件派发给Activity/Dialog。
而PopupWindow/Toast都是用一个ViewGroup作为窗口的View,因此PopupWindow/Toast本身不具备获取输入事件的能力,输入事件是直接派发到了View tree。由于PopupWindow/Toast也是通过WindowManagerImpl添加的窗口,因此他们都有对应的ViewRootImpl, 因此也就具备了与WMS通信和事件派发的能力。
Activity/Dialog/PopupWindow/Toast与WindowState
Activity/Dialog/PopupWindow/Toast在WMS都有对应的WindowState,只是Activity/Dialog/PopupWindow的WindowState属于同一个AppWindowToken,也就是Activity的token,而Toast的WindowState属于自己独有的WindowToken。