1. 前言

Window是一个抽象类,它的具体实现是PhoneWindow,WindowManager是外界访问Window的入口,Window的具体实现位于WindowManagerService中,WindowManagerService和WindowManager的交互是一个IPC的过程。Window实际是View的管理者。

2. Window和WindowManager的使用

WindowManager.LayoutParams中的flags与type是两个重要的参数。

2.2 flags参数

表示Window的属性,可以控制Window的显示特性,比较常用的参数如下:

  • FLAG_NOT_FOCUSABLE: 表示Window不需要获取焦点,也不需要接收任何输入事件,此标记同时也启用FLAG_NOT_TOUCH_MODEL,最终事件会直接传递给下层的具有焦点的Window;
  • FLAG_NOT_TOUCH_MODEL: 系统会将当前区域以外的事件传递的给底层Window,区域以内的事件由自己处理,一般都需要开启此标记,否则其他Window无法接收到事件;
  • FLAG_SHOW_WHEN_LOCKED: 让Window在锁屏的界面上显示;
2.3 type参数

表示Window的类型,主要有三种类型:应用Window、子Window、系统Window

  • 应用类Window:对应着一个Activity;
  • 子Window:需要附属在父Window之中,例如:常见的Dialog;
  • 系统Window:需要声明权限在能创建的Window,例如:Toast和系统状态栏这些都是系统Window;

Window是分层的,每个Window都有对应的z-ordered,层级大的覆盖在层级小的Window上面。在这三类type的Window中,层级关系:系统Window > 子Window > 应用Window

如果想要Window位于所有Window的最顶层,那么采用较大的层级即可。显然系统Window的层级是最大的,系统层级有很多值,一般我们选用TYPE_SYSTEM_OVERLAY或者TYPE_SYSTEM_ERROR,使用的时候给type参数指定这个值,并声明权限,因为系统类型的Window是需要检查权限的

2.4 WindowManager使用

WindowManager提供的功能很简单,即常用的三个方法:添加View、更新View、删除View,这三个方法定义在ViewManager中,而WindowManager继承自ViewManager

应用场景:Window的拖动。根据手指位置,不断更新LayoutParams中的 x 和 y 的值即可改变Window的位置。

3. Window的内部机制

Window是一个抽象的概念,每个Window都对应着一个View和一个ViewRootImpl,Window和View之间通过ViewRootImpl来建立联系,因此Window并不存在,它是以View的形式存在的,即View才是Window的实体。在实际使用中无法直接访问Window,仅能通过WindowManager来进行对Window的访问。

3.1 Window的添加过程

Window的添加过程是通过WindowManager的addView来实现的,WindowManager是一个接口,真正实现的是WindowManagerImpl。

在WindowManagerImpl中,并没有直接实现Window的三个操作,而是交由WindowManagerGlobal来处理。WindowManagerGlobal以工厂形式想外提供自己的单例。

WindowManagerImpl的这种工作模式就是桥接模式,将所有的操作交由WindowManagerGlobal来处理。

WindowManagerGlobal的addView的方法主要分为如下步骤:

  1. 检查参数(view、display、params)是否合法,如果是子Window那么还需要调整一些布局参数

  2. 创建ViewRootImpl并将View添加到列表中,其中有 4 个存储列表:

    1. mViews:存储所有Window对应的View
    2. mRoots:存储所有Window对应的ViewRootImpl
    3. mParams:存储所有Window对应的布局参数
    4. mDyingViews:存储正在被删除的View对象,或者是已经调用了removeView方法但是删除操作还没完成的Window对象
  3. 通过ViewRootImpl来更新界面并完成Window的添加过程:该步骤通过调用ViewRootImpl的setView方法来完成,在setView内部会通过requestLayout操作来完成异步刷新请求。scheduleTraversals实际是View绘制的入口

  4. 接着通过WindowSession来完成Window的添加过程,其类型是IWindowSession,它是一个Binder对象,真正的实现类是Session,也就是Window的添加过程实际上是一次IPC调用。其在Session内部会通过WindowManagerService来实现Window的添加。

  5. 最终Window的添加请求交由WindowManagerService完成,在WindowManagerService内部会为每一个应用保留单独的Session。

3.2 Window的删除过程
  1. 先通过WindowManagerImpl,随后通过WindowManagerGlobal来实现,调用removeView完成Window的删除操作
  2. 在removeView中,通过findViewLocked来查找待删除的View的索引,这个查找过程就是数组遍历,然后再调用removeViewLocked来做进一步删除,其是通过ViewRootImpl来完成删除操作的。在WindowManager 中有两个删除接口 removeView 和 removeViewImmediate,分别表示 同步删除 和 异步删除。
  3. 通过使用异步删除Window的方式,removeView内部由ViewRootImpl的 die 方法来完成,die方法发送一个删除请求的消息后就立马返回了,这时View并还没有删除,所以最后会将其添加到 mDyingViews 列表中
  4. 在die方法中,如果是异步删除,则发送一个MSG_DIE的消息,ViewRootImpl中的Handler会处理此消息并调用die方法;若是同步删除,则会直接调用doDie方法,不会发送消息。在 doDie 方法内部会调用 dispatchDetachedFromWindow,真正的删除操作再其内部实现。
  5. 在dispatchDetachedFromWindow中,主要做了如下操作:
    1. 垃圾回收工作。如清除数据和消息、移除回调;
    2. 通过Session的remove方法删除Window:通过mWindowSession.remove,随后通过IPC方式,调用WindowManagerService的removeView方法
    3. 调用View的 dispatchDetachedFromWindow 方法,在内部会调用View的 onDetachedFromWindow 和 onDetachFromWindowInternal。对于onDetachFromWindow方法,当View从Window中移除时,该方法一定会被调用,其内部做一些资源回收的工作,如终止动画,停止线程等
    4. 调用WindowManagerGlobal的doRemoveView方法刷新数据,包括mRoots、mParams及mDyingViews,将当前Window所关联的这三类对象移除
3.3 Window的更新过程
  1. 跟addView、removeView类似,最终调用WindowManagerGlobal的updateViewLayout方法
  2. updateViewLayout的方法做的事情相对简单,首先更新View的LayoutParams,然后通过findViewLocked找到View的索引,删除mParams中就有的LayoutParams,在索引上添加新的layoutParams,接着更行ViewRootImpl中的LayoutParams。
  3. 在ViewRootImpl中会通过调用scheduleTraversals方法来对View重新绘制,包括测量、布局、绘制。除了View自身重绘,还会通过WindowSession来更新Window的视图,最终依旧交由WindowManagerService的relayoutWindow方法来实现。

4. Window的创建过程

View不能单独存在,它需要附着在Window上面,因此有视图的地方就有Window。

4.1 Activity的Window创建过程

Activity的启动过程很复杂,最终会由ActivityThread中的performLaunchActivity来完成整个启动过程,在这个方法内部会通过类加载器来创建Activity的实例对象,并调用attach方法来为其关联运行中所依赖的一系列上下文环境变量。

在Activity的attach方法中,系统会为其创建Activity所属的Window对象并为其设置回调接口,Window对象的创建是通过PolicyManager的makeNewWindow来实现的。

由于Activity实现了Window的Callback接口,因此当Window接收到外界的状态改变时就会回调Activity的方法。Callback接口中有很多方法,常用的是:onAttachedToWindow、onDetachedFromWindow、dispatchTouchEvent等等

Activity的Window由PolicyManager创建的,在实际的调用中,PolicyManager的真正实现是Policy类,在Policy类的makeNewWindow中,创建了一个PhoneWindow。

Window的创建已经完成了,接下来,分析下Activity的视图是如何附属在Window上的,首先将分析Activity的setContentView方法。在Activity的setContentView方法中,Activity将具体的实现交由Window处理,而Window的具体实现是PhoneWindow,所以接下来看下PhoneWindow中的相关逻辑。

  1. 如果没有DecorView,就去创建它:DecorView是Activity中的顶级View,内部包含标题栏和内容栏。DecorView的创建过程由installDecor来完成,在方法内部通过generateDecor方法来直接创建DecorView,这个时候的DecorView还是一个空白的FrameLayout。除此之外,还将会调用generateDecor方法将布局文件加载到DecorView中。
  2. 将View添加到DecorView的mContentParent中:通过inflate将Activity的视图直接添加到DecorView的mContentParent中。
  3. 回调Activity的onContentChanged方法通知Activity视图已经发生改变:由于Activity实现了Window的Callback接口,这里表示Activity的视图已经被添加到DecorView的mContentParent中,于是通知Activity。
  4. 经过了上述的三个步骤后,此时的DecorView已经被创建且初始化完成,Activity的视图文件也添加到DecorView的mContentParent中,但是这个时候DecorView还没被WindowManager正式添加到Window中。虽然在Activity的attach方法中创建了Window,但是这个时候DecorView还没有被WindowManager识别,所以此时的Window无法提供具体功能,无法接受外界的信息。在ActivityThread的handleResumeActivity中,首先会调用Activity的onResume方法,随后会调用Activity的makeVisible方法,在makeVisible中,DecorView完成真正的添加和显示过程,至此Activity的视图才可被用户所见。
4.2 Dialog的Window创建过程
  1. 创建Window:同样通过 PolicyManager 的 makeNewWindow 来创建 Window,创建后的对象依旧是PhoneWindow,与 Activity 的创建 Window 过程一样。
  2. 初始化 DecorView 并将 Dialog 的视图添加到DecorView中。
  3. 将DecorView添加到Window中并显示。

注意:应用token一般只有Activity拥有,系统Window比较特殊,可以不需要token。因此当应用Window使用ApplicationContext时,运行会报错。所以Dialog的Window创建默认需闯入Activity的Context。

4.3 Toast的Window创建过程
  1. Toast的具体定时功能,所以系统才用了Handler。
  2. 在Toast里由两类IPC过程,一个是Toast访问的 NotificationManagerService ,另一个是NotificationManagerService 回调的Toast里的 TN 接口。
  3. Toast属于系统 Window,其内部有两种方式指定视图,一种是系统默认的方式,另一种是通过setView方式来指定,不管哪种方式,都对应着Toast的mNextView。Toast的 show 和 cancel 方法内部都是IPC过程。
  4. 在Toast显示过程中,调用 NMS 的 enqueueToast 方法,将Toast请求封装成 ToastRecord 添加到mToastQueue中,其容量为50,为了防止恶意的DOS攻击service.enqueueToast(pkg, tn, mDuration)
  5. Toast的显示与隐藏分别调用 handleShow 和 handleHide 方法。

注意:由于Toast的显示与隐藏涉及到 IPC 过程,所以涉及到 Binder 来跨进程通信。TN 是一个 Binder 类,当Toast处理显示或者隐藏的时候,都会回调TN这个接口。这时TN运行在Binder线程池中,需要通过Handler来切换到当前线程,因此Toast无法在没有Looper的线程中弹出。

Android-Window和WindowManager相关推荐

  1. Android Window、WindowManager、WMS

    1.窗口Window 一个app从启动到主窗口显示出来,需要app.AMS.WMS.SurfaceFlinger(SF)等几个模块相互合作.app负责业务逻辑,绘制自己的视图:AMS管理组件.进程信息 ...

  2. Android开发艺术探索》读书笔记 (8) 第8章 理解Window和WindowManager

    第8章 理解Window和WindowManager 8.1 Window和WindowManager (1)Window是抽象类,具体实现是PhoneWindow,通过WindowManager就可 ...

  3. Android之Window与WindowManager

     Window表示一个窗口的概念,在日常开发中直接接触Window的机会并不多,但却会经常用到Window,activity.toast.dialog.PopupWindow.状态栏等都是Window ...

  4. Android GUI之Window、WindowManager

    通过前几篇的文章(查看系列文章:http://www.cnblogs.com/jerehedu/p/4607599.html#gui ),我们清楚了Activity实际上是将视图的创建和显示交给了Wi ...

  5. Android中的Window、WindowManager以及悬浮框视频播放的实现

    摘要:近日看公司直播项目,其中有一个功能就是退出某房间之后,直播界面会以悬浮窗的形式出现,并且可以拖动悬浮窗到界面中任意位置,点击悬浮框之后,又可以回到房间中继续观看直播.现在这个功能在主流的直播或者 ...

  6. Android源码分析之理解Window和WindowManager

    Window和WindowManager概述 Window是一个抽象类,它的具体实现是PhoneWindow,创建一个Window通过WindowManager 就可以完成.WindowManager ...

  7. Activity Window View WindowManager关系Touch事件分发机制

    http://www.cnblogs.com/linjzong/p/4191891.html https://www.cnblogs.com/kest/p/5141817.html https://b ...

  8. Window与WindowManager

    相关类: Window:是一个抽象类,只是一个概念并不实际存在,唯一实现类是PhoneWindow,其对View进行管理 WindowManager:一个接口类,继承自ViewManager,字面意思 ...

  9. Android Window Manager Subsystem Research

    Copyright:http://blog.csdn.net/myzhzygh/article/details/8470469 1.Introduce 本文档的主要目的是记录Android 窗口子系统 ...

  10. android window manager

    一.概述 在Android系统中,从设计的角度来看,窗口管理系统是基于C/S模式的.整个窗口系统分为服务端和客户端两大部分,客户端负责请求创建窗口和使用窗口,服务端完成窗口的维护,窗口显示等. 在Cl ...

最新文章

  1. 2021年春季学期-信号与系统-第五次作业参考答案
  2. 微软一站式示例脚本库 — IT专业人士的省时利器
  3. asp.net MVC分页
  4. ubuntu_常用命令_01
  5. 【OpenGL从入门到精通(三)】第一个点的理论
  6. mysql 3种报错_MySQL读取Binlog日志常见的3种错误-阿里云开发者社区
  7. Unicode 和 UTF-8 有什么区别?
  8. Java IdentityHashMap put()方法与示例
  9. JavaEE实战班第18天
  10. 构造Linux流媒体服务器收藏
  11. 计算机软件系统包括选择题,青书学堂: (单选题) 计算机软件系统包括 ( )(本题2.0分)...
  12. 文档交接说明书(模板)
  13. Java从服务器下载文件到本地
  14. 认识SFP/SFP+/QSFP/QSFP+光模块
  15. KITTI 3D目标检测离线评估工具包说明
  16. 26.gateway的IP 认证拦截,gateway做token验证 流程图(springcloud)
  17. 计算机发展史上有杰出贡献的科学家,山东省计算机文化基础考试练习题
  18. Web应用程序的身份验证机制
  19. 【解决报错问题:selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurr】
  20. js 金钱格式化(money)

热门文章

  1. USB之ch376s数据手册
  2. Fatal NI connect error 12170.
  3. day01 C语言基础
  4. iMeta | 易扩增子(EasyAmplicon):易用、可重复的微生物组扩增子分析流程
  5. C++ 命令行版贪吃蛇(附下载地址)
  6. 香橙派orange pi c# iot .net 读取温湿传感器 芯片sht30 I2C 代码实例
  7. PrivacyPolicy 隐私政策(鑫炳优品)
  8. 现代C++教程笔记(下)
  9. go使用epoll或kqueue
  10. 联想rd450x服务器风扇转速调节