WMS相关知识点(一)

4 篇文章 0 订阅
3 篇文章 0 订阅

一、 Window、WindowManager、WMS

Window:在Android视图体系中Window就是一个窗口的概念。Android中所有的视图都是依赖于Window显示的。

  window 它是一个抽象类,具体实现类为 PhoneWindow ,它对 View 进行管理。Window是View的容器,View是Window的具体表现内容。

每个Activity都对应有一个Window
应用程序窗口、PopupWindow、输入法窗口、Toast、Dialog、系统错误窗口等都是比较常见的Window

WindowManager:是一个接口类,继承自接口ViewManager,从它的名称就知道它是用来管理 Window 的,它的实现类为 WindowManagerImpl。对Window的管理,包括新增、更新和删除等。

横竖屏切换、配置的变化都会导致Window的更新
Dialog的dismiss()就是window的删除操作

WindowManagerService(WMS):窗口的最终管理者,它负责窗口的启动、添加和删除,另外窗口的大小和层级也是由WMS进行管理。
三者的关系:

在这里插入图片描述

二、 WindowManager 的关联类

在这里插入图片描述

这个地方采用桥接模式

  ​ WindowManager 其实是一个接口,它继承自 ViewManager , ViewManager 中定义了 3 个抽象方法,分别是用来添加、更新、删除 View 的,WindowManager 继承了父类接口的方法,说明也具备了父类的能力。
​  ​ WindowManagerImpl是WindowManager的实现类,但是具体的功能都会委托给WindowManagerGlobal来实现。

三、 Window的类型

  ​Window 的类型有很多种,比如应用程序窗口、系统错误窗口、输入法窗口、PopWindow、Toast、Dialog 等。总的来说 Window 分为三大类型,分别是 Application Window(应用程序窗口)Sub Window(子窗口)System Window (系统窗口),每个大类型中又包含了很多种类型,它们都定义在 WindowManager 的静态内部类 LayoutParams 中,接下来分别对这三大类型进行讲解。

  • Application Window:Activity就是一个典型的应用程序窗口。
    应用程序的窗口的 Type 值范围为 1~99,这个值的大小涉及窗口的层级。

    //WindowManager.java
    /**
     * 表示应用程序窗口类型初始值
     */
    public static final int FIRST_APPLICATION_WINDOW = 1;
     /**
      * 窗口的基础值,其它的窗口值要大于这个值
      */
    public static final int TYPE_BASE_APPLICATION   = 1;
    /**
     * 普通的应用程序窗口
     * 
     */
    public static final int TYPE_APPLICATION        = 2;
    /**
     * 应用程序启动窗口的类型,用于系统在应用程序窗口启动前显示的窗口
     */
    public static final int TYPE_APPLICATION_STARTING = 3;
    
    public static final int TYPE_DRAWN_APPLICATION = 4;
    /**
     * 表示应用程序窗口类型的结束值值的范围是 1~99
     */
    public static final int LAST_APPLICATION_WINDOW = 99;
    
  • Sub Window:子窗口,顾名思义,它不能独立存在,需要附着在其他窗口才可以,PopupWindow就属于子窗口。
    子窗口的Type值范围为1000~1999

    跟父窗口共用一个token

    //WindowManager.java
    /**
     * 子类窗口初始化值
     */
    public static final int FIRST_SUB_WINDOW = 1000;
    
    public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
    
    public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
    
    public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;
    
    public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;
    public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW + 4;
    
    public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
    /**
     * 子类窗口类型结束值
     */
    public static final int LAST_SUB_WINDOW = 1999;
    
  • System Window:​ 比如 Android 中的 Toast、输入法窗口、系统音量条窗口、系统错误窗口、顶部状态栏通知栏、Toast都是属于系统级别的 Window 。​ 系统窗口的类型值有接近 40 多个,这里只列举了部分,系统窗口的 Type 值范围为 2000 - 2999。

     /**
     * 系统类型窗口类型初始值
     */
    public static final int FIRST_SYSTEM_WINDOW     = 2000;
    
    /**
     * 系统状态栏窗口
     */
    public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;
    
    /**
     * 搜索条窗口
     */
    public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;
    
    /**
     * 通话窗口
     */
    @Deprecated
    public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;
    
    /**
     * 系统 alert 窗口
     */
    @Deprecated
    public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
    
    /**
     * 系统锁屏窗口
     */
    public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
    
    /**
     * Toast 窗口
     */
    @Deprecated
    public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
    
            ...
    /**
     * 系统窗口类型的结束值
     */
    public static final int LAST_SYSTEM_WINDOW      = 2999;
    

Type值越大,Z轴越大,窗口越靠前

窗口的次序:
  最上层的一定是系统窗口System Window,之后是子窗口Sub Window,最下面是应用程序窗口Application Window

不同类型的窗口的排列次序:
在这里插入图片描述

四、 Window的标志

  ​ Window 的标志也就是 Flag, 用于控制 Window 的现实,同样被定义在 WindowManager 的内部类 LayoutParams 中,一共有 20 多个,这里给出几个比较常用的,如下:

Window Flag说明
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON只要窗口可见,就允许在开启状态的屏幕上锁屏
FLAG_NOT_FOCUSABLE窗口不能获得输入焦点,设置该标志的同时,FLAG_NOT_TOUCH_MODAL 也会被设置
FLAG_NOT_TOUCHABLE窗口不接收任何触摸事件
FLAG_NOT_TOUCH_MODAL将该窗口区域外的触摸事件传递给其它的 Window,而自己只会处理窗口区域内的触摸事件
FLAG_KEEP_SCREEN_NO只要窗口可见,屏幕就会一直常亮
FLAG_LAYOUT_NO_LIMITS允许窗口超过屏幕之外
FLAG_FULISCREEN隐藏所有的屏幕装饰窗口,比如在游戏、播放器中的全屏显示
FLAG_SHOW_WHEN_LOCKED窗口可以在锁屏的窗口之上显示
FLAG_IGNORE_CHEEK_PRESSES当用户的脸贴近屏幕时(比如打电话),不会去响应事件
FLAG_TURN_SCREEN_NO窗口显示时将屏幕点亮

设置 Window 的 Flag 有 3 种方法:

  • 通过 Window 的 addFlag 方法

    Window mWindow = getWindow();
    mWindow.addFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    
  • 通过 Window 的 setFlags 方法

    Window mWindow = getWindow();
    mWindow.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN)
    
  • 给 LayoutParams 设置 Flag, 并通过 WindowManager 的 addView 方法进行添加

    WindowManager.LayoutParams mWindowLayoutParams = new WindowManager.LayoutParams();
    mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN;
    WindowManager mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
    Text mText = new Text(this);
    mWindowManager.addView(mTextView,mWindowLayoutParams);
    

五、 软件盘相关模式

​  窗口与窗口的叠加是十分常见的场景,但是如果其中的窗口是软件盘的窗口,可能就会出现一些问题,比如典型的用户登录页面,默认的情况弹出软件盘窗口可能遮挡输入框下方的按钮,这样用户体验非常糟糕。为了使得软键盘窗口能够按照期望来显示,WindowManager 的静态内部类 LayoutParams 中定义了软件盘相关模式,这里给出常用的几个:

SoftInputMode描述
SOFT_INPUT_STATE_UNSPECIFIED没有设定状态,系统会选择一个合适的状态或依赖于主题的设置
SOFT_INPUT_STATE_UNCHANGED不会改变软键盘状态
SOFT_INPUT_STATE_ALWAYS_HIDDEN当窗口获取焦点时,软键盘总是被隐藏
SOFT_INPUT_ADJUST_RESIZE当软键盘弹出时,窗口会调整大小
SOFT_INPUT_ADJUST_PAN当软键盘弹出时,窗口不需要调整大小,要确保输入焦点是可见的
SOFT_INPUT_STATE_HIDDEN当用户进入该窗口时,软键盘默认隐蔽

​  从上面给出的 SoftInputMode,可以发现,它们与 AndroidManifest.xml 中 Activity 的属性 android:windowsoftInputMode 是对应的。因此,除了在 AndroidManifest.xml 中为 Activity 配置还可以通过代码动态配置,如下所示:

geWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

六、添加Window

在这里插入图片描述
  Activity#attach()方法之内PhoneWindow创建,并同时创建----WindowManagerImpl负责维护PhoneWindow内的内容。
  在Activity#onCreate()中调用setContentView()方法,这个方法内部创建一个DecorView实例作为PhoneWindow的内容。
  WindowManagerImpl决定管理DecorView,并创建一个ViewRootImpl实例,将ViewRootImplView树进行关联,这样ViewRootImpl就可以指挥View树的具体工作。

七、 DecorView

activity 与 PhoneWindow 与 DecorView 关系
在这里插入图片描述
  DecorView是FrameLayout的子类,它可以被认为是Android视图树的根节点视图
  ​ 在Activity的生命周期onCreate()方法里面,是会设置好布局内容通过setContentView(布局id)的方式,这里是通过xml解析器转化为一个View,这个View会被添加到ContentView中去,成为唯一的子View

八、 WindowManagerImpl、WindowManagerGlobal、ViewRootImpl

  ​WindowManagerGlobal是一个单例类,一个进程只有一个实例。它管理者所有Window的ViewRootImpl、DecorView、LayoutParams。
  ​ViewRootImpl是View树的树根,但它却又不是View实现了View与WindowManager之间的通信协议,在WindowManagerGloble中的addView中被建立,是顶层DecorView的ViewParent。
ViewRootImpl作用:
① View树的树根并管理View树
② 触发View的测量、布局和绘制
③ 输入响应的中转站
④ 负责与WMS进行进程间通信(通过binder)
在这里插入图片描述

  一个Activity对应一个PhoneWindow,一个PhoneWindow里面包含一个WindowManagerImpl和一个DecorView,一个WindowManagerImpl对应一个ViewRootImpl,WindowManagerGlobal是一个全局的管理者。

  • WindowManagerImpl主要功能:确定View属于哪个屏幕、哪个父窗口(确定窗口

  • WindowManagerGlobal主要功能:管理整个进程 所有的窗口信息,即主要包含view(DecorView)、root(ViewRootImpl)、wparams(WindowManager.LayoutParams)(管理信息

    每个进程都对应一个WindowManagrGlobal,也就说每个app进程都对应有自己的WindowManagrGlobal

  • ViewRootImpl主要功能:WindowManagerGlobal实际操作者,操作自己的窗口(做大量的事情,真正的执行者

    ViewRootImpl存在多个,一个窗口对应一个ViewRootImpl

绘制流程:
在这里插入图片描述
更新Window:
在这里插入图片描述
  ViewRootImpl.scheduleTraversals()打报告进行刷新,信号服务中心会收到VSYNC信号,收到信号之后会重新发送一个同步信号给到Choreographer编舞者,最后就会执行到ViewRootImpl.performTraverals()。即window刷新或view的刷新,最后都会调用到ViewRootImpl.performTraverals()方法中

UI刷新流程:
在这里插入图片描述
申请Vsync流程:
在这里插入图片描述
  等到VSYNC到来后,会移除同步栅栏,并率先开始执行当前帧的处理,调用逻辑如下:
在这里插入图片描述

在这里插入图片描述


SurfaceFlinger
  SurfaceFlinger是整个Android系统渲染的核心进程。所有应用的渲染逻辑最终都会来到SufaceFlinger中进行处理,最终会把处理后的图像数据交给CPU或者GPU进行绘制。
  在每一个应用中都以Surface作为一个图元传递单元,向SurfaceFlinger这个服务端传递图元数据。
在这里插入图片描述

SurfaceFlinger整体流程:

在这里插入图片描述
  SurfaceFlinger是以生产者以及消费者为核心设计思想,把每一个应用进程作为生产者生产图元保存到SurfaceFlinger的图元队列中,SurfaceFlinger则作为消费者依照一定的规则把生产者存放到SurfaceFlinger中的队列一一处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值