Window和WindowManager

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显示在锁屏的页面上。
  • 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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容