Android:窗口管理器WindowManager

本文详细解析了Android中的窗口概念、WindowManager的作用,涉及Window类型、属性、标志,以及PhoneWindow和WindowManagerImpl的实现。重点介绍了ViewRootImpl在窗口管理中的角色,以及如何在子线程更新UI的特殊情况。

Android:窗口管理器WindowManager

在这里插入图片描述

导言

本篇文章主要是对Android中与窗口(Window)有关的知识的介绍,主要涉及到的有:

  1. Window
  2. WindowManager
  3. WindowManagerService

主要是为了更进一步地向下地深入Android屏幕渲染的知识(虽然窗口可能并算不上)。

窗口(Window)

Q:什么是窗口

实际上Android上的窗口指的并不是具体的手机窗口而是一个抽象的概念,它本质上也是一个View,我会把窗口理解成一组有关联的View

ActivityManagerActivityManagerService的关系类似,WindowManager中方法的实现也是通过远程调用WindowManagerService实现的:

在这里插入图片描述

窗口的属性

窗口的类型

Window的类型大体来分有三种,我们可以在源文件中找到具体的对应:
在这里插入图片描述

    1. 应用程序窗口:最常见的,顶层应用的显示窗口
    1. 子窗口:需要依附在其他窗口的窗口
    1. 系统窗口: Toast,系统输入法窗口,系统错误窗口等

另外,每种窗口还有其对应的TYPE值,这个值主要是用来确定窗口的显示层次的,应用程序窗口的TYPE值在1-99范围内,子窗口在1000-1999,系统窗口在2000-2999。至于这个TYPE值会如何影响显示层次呢?这里我们可以简单的将这个TYPE值看做是一个z轴的坐标值,也就是垂直于手机屏幕的距离,数值越大,其离手机屏幕就越远,那么显示的优先级也会越高。

当然,实际的情况比这要复杂,会涉及到一些加权的计算,这里我们先简单这样理解即可。

窗口的标志

窗口的标志决定了窗口的一些响应特性,这里直接给出一些常用的flag理解一下:

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 只要窗口可见,就会一直保持长亮
FLAG_LAYOUT_NO_LIMITS 允许窗口显示在手机屏幕之外

Window的具体实现类PhoneWindow

这个PhoneWindow我们应该在Activity的setContentView方法中有提及到,这里再简单回顾一下:

    public void setContentView(@LayoutRes int layoutResID) {
   
   
        initViewTreeOwners();
        getDelegate().setContentView(layoutResID);
    }
    //Activity.java中
    public void setContentView(View view, ViewGroup.LayoutParams params) {
   
   
        getWindow().setContentView(view, params);
        initWindowDecorActionBar();
    }

当我们调用Activity的setContentView方法时首先会根据后面传入的xml布局文件初始化整棵视图树,之后会获取到Activity自身对应的Window对象,也就是描述Activity该如何显示的一个View,之后再调用该Window的setContentView方法,那这个Window对象是在何处被初始化的呢?答案是在Activity的attach方法中,该方法是在ActivityThread中被调用的:

final void attach(...) {
   
   
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        ......
        mWindow.setWindowManager(
        (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
        mToken, mComponent.flattenToString(),
        (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    }

可以清楚的看到此处将Activity对应的PhoneWindow对象实例创建了出来,并将这个对象与一个WindowManager对象绑定起来,所以说上面Activity调用的setContentView最终是由这个PhoneWindow对象实例来完成的,最终就会在PhoneWindow中安装一个DecorView,DecorView作为整个PhoneWindow中的第一个View(实际上的根View),并把xml中的内容填充进DecorView的内容部分。

WindowManager(窗口管理者)

WindowManager接口

接下来我们从源码角度先分析一下WindowManager:

public interface WindowManager extends ViewManager

可以看到WindowManager本质上是一个继承了ViewManager接口的一个接口,因为ViewManager比较简单,我们先来看ViewManager接口:

public interface ViewManager
{
   
   
    public void 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值