
注:以下内容基于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
。