Window和WindowManager
标签(空格分隔): android
一些简单的定义:
- WindowManager是外界访问Window的入口(相当于代理人),window的具体实现位于WindowManagerService中,WindowManager和WindowManagerService的交互是一个IPC过程。
- android中所有的视图都是tongguowindow呈现出来的,Window是是view的直接管理者,它会将事件传递给顶层View--DecorView。
WindowManager添加一个Window
mWindowManager.addView(mButton,mLayoutParams);
- 值得一说的东西:WindowManage.layoutParams的两个参数----flags和type。
- Flag表示Window的属性。
1、FLAG_NOT_FOCUSABLE:window不获取焦点,不接受各种输入事件,事件传递给下层具有焦点的window。
2、FLAG_NOT_TOUCH_MODAL:系统会将当前Window区域以外的点击事件传递给底层的Window,当前的window区域内的点击事件则自己处理。
3、FLAG_SHOW_WHEN_LOCKED:让window显示在锁屏的页面上。
- Flag表示Window的属性。
- Type是window的类型,应用window(对应一个Activity)、子window(需要依附一个父window)、系统window(toast等)。
- window的z-ordered
1、应用window的层级范围是199,子window层级范围是10001999,系统window层级范围是2000~2999.
2、层级越大优先级越大。
Window内部机制
简单介绍:
每一个window都对应一个view和viewRootImpl,window和view通过viewRootImpl建立联系,window的访问必须通过windowManager。
window的添加过程
其实对window的操作是以下的流程:
windowManager---》windowManagerImpl---》windowManagerGlobal
大致流程如下:
1、检查参数是否合法,如果有子window那么还需要一些布局参数。
2、创建ViewRootImpl并将View添加到列表。WindowManagerGlobal内部有几个列表,分别是View、ViewRootImpl、mparams、待删除的View列表。
3、通过ViewRootImpl来更新页面并完成Window的添加过程。
大致流程:setView(ViewRootImpl)-->scheduleTraversals(requestLayout)-->windowSession(Binder对象)-->addToDisplay(IPC调用)--> windowManagerService
4、通过WindowManagerService进行Window的添加。
window的删除过程
和window的添加过程一样,最终实现都是在windowManagerGlobal实现的(具体方法就是removeView)。
- removeView的逻辑:首先通过findViewLocked来查找待删除的View索引(就是数组的遍历),然后通过调用removeViewLocked来做进一步的删除。
-
removeViewLocked的内部实现:
- dispatchDetachedFromWindow的功能:
- 垃圾回收相关工作,如清理数据等。
- 通过Session的remove方法删除Window,一个IPC过程。
- 通过View的dispatchDetachedFromWindow方法,在内部会调用View的onDetachedFromWindow,主要用于资源回收。
- 调用WindowManagerGlobal的doRemoveView方法刷新数据,更新前面所说的列表。
window的更新,就不详说了,大概流程和前面两个差不多。(开发探索P304)
一些重要的Window
Activity的Window创建过程
- window的创建实现是在Activity的attach方法里面,系统会创建Activity所属的Window对象并为其回调接口,Window对象的创建是通过PolicyManager的makeNewWindow方法实现。
- Policy的真正实现是Policy类,Policy类的makeNewWindow方法,其实具体实现是PhoneWindow。
- 所以让我们一起来看看PhoneWindow的setContentView方法:
- 如果没有DecorView,就创建它。(installDecor--->generateDecor(这个方法直接创建DecorView))
- 将View添加到DecorView的mContentParent中。
- 回调Activity的onCreateChanged方法通知Activity视图发生变化。(handleResumeActivity-->onResume-->makeVisible)
Dialog的Window创建过程
1、创建Window。
2、初始化DecorView并将Dialog的视图添加到DecorView中。
3、将DecorView添加到Window中并显示
4、Dialog被销毁时,通过WindowManager来移除DecorView:removeViewImmediate。
特殊之处:必须采用Activity的上下文Context
Toast的Window创建过程
- Toast内部有两类IPC过程,第一类是Toast访问NMS(NotificationManagerService),第二类是NMS回掉Toast里面的TN接口。
- 由于Toast的隐藏和显示会涉及到跨进程调度,需要用到TN接口,TN接口其实现是Binder线程池,需要Handler切换线程,所以Toast不能在没有Looper的线程中使用。(详见消息机制)。
- Toast的显示:
NMS中的enqueueToast方法(第一个参数是包名,第二个参数是tn,第三个参数是toast显示的时长)---将Toast封装成一个ToastRecord对象,然后添加到mToastQueue队列里面。 ---》 NMS中的showNextToastLocked方法显示当前Toast(其调度是一个IPC过程,) ---》NMS的scheduleTimeoutLocked方法(发送一条延时消息,取决于Toast的时长) ---》 NMS中的cancelToastLocked方法隐藏Toast并将其从mToastQueue移除(出队列,同样也是IPC调用)。
总结:
一个Window对应一个View。
其调度是一个IPC过程,需要用到消息机制,即Handler。