Android Framework解析——WMS原理

作者:bobby_developer

1. WMS原理:WMS角色与实例化过程

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

  • windowManager:是一个接口类,继承自接口 ViewManager ,从它的名称就知道它是用来管理 Window 的,它的实现类为 WindowManagerImpl;

  • WMS:是窗口的管理者,它负责窗口的启动、添加和删除。另外窗口的大小和层级也是由它进行管理的;

SystemServer启动WMS流程表:

1.1 window

1.2 显示层级

1.3 窗口标志位

1.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON(当Window可见时允许锁屏)
2.FLAG_NOT_FOCUSABLE(Window 不能获得输入焦点,即不接受任何按键或按钮事件,例如该 Window 上 有 EditView,点击 EditView 是 不会弹出软键盘的,Window 范围外的事件依旧为原窗口处理;例如点击该窗口外的view,依然会有响应。另外只要设置了此Flag,都将会启用FLAG_NOT_TOUCH_MODAL) 3.FLAG_NOT_TOUCH_MODAL(设置了该 Flag,将 Window 之外的按键事件发送给后面的 Window 处理, 而自己只会处理 Window 区域内的触摸事件;Window 之外的 view 也是可以响应 touch 事件。 4.FLAG_NOT_TOUCHABLE(设置了该Flag,表示该 Window 将不会接受任何 touch 事件,例如点击该 Window 不会有响应,只会传给下面有聚焦的窗口) 5.FLAG_KEEP_SCREEN_ON(只要 Window 可见时屏幕就会一直亮着,视频播放、游戏) 6.FLAG_LAYOUT_NO_LIMITS(允许 Window 超过屏幕之外)
7.FLAG_IGNORE_CHEEK_PRESSES(当用户的脸贴近屏幕时(比如打电话),不会去响应此事件 )
8.FLAG_SHOW_WHEN_LOCKED(当用户的脸贴近屏幕时(比如打电话),不会去响应此事件
9.FLAG_IGNORE_CHEEK_PRESSES ; 窗口可以在锁屏的 Window 之上显示, 使用Activity#setShowWhenLocked(boolean) 方法代替)

1.4 WindowManager

在了解WindowManager管理View实现之前,先了解下WindowManager相关类图以及Activity界面各层级显示关系;

2. WMS工作原理

2.1 WMS职责

2.2 WMS中重要的一些属性释义

2.3 AddWindow源码分析

WMS中addWindow源码分析,在分析addWindow之前,先了解几个类;

  • WindowToken

    WindowToken具有令牌的作用,是对应用组件的行为进行规范管理的一个手段。WindowToken由应用组件或其管理者负责向WMS声明并持有。应用组件在需要新的窗口时,必须提供WindowToken以表明自己的身份,并且窗口的类型必须与所持有的WindowToken的类型一致,同时它将属于同一个应用组件的窗口组织在了一起;

  • DisplayContent

    如果说WindowToken按照窗口之间的逻辑关系将其分组,那么DisplayContent则根据窗口的显示位置将其分组。隶属于同一个DisplayContent的窗口将会被显示在同一个屏幕中。每一个DisplayContent都对应这一个唯一的ID,在添加窗口时可以通过指定这个ID决定其将被显示在那个屏幕中。DisplayContent是一个非常具有隔离性的一个概念。处于不同DisplayContent的两个窗口在布局、显示顺序以及动画处理上不会产生任何耦合。因此,就这几个方面来说,DisplayContent就像一个孤岛,所有这些操作都可以在其内部独立执行。因此,这些本来属于整个WMS全局性的操作,变成了DisplayContent内部的操作了。

  • WindowState 表示一个窗口的所有属性,所以它是WMS中事实上的窗口;当向WMS添加一个窗口时,WMS会为其创建一个WindowState。另外WMS.addWindow()函数中看到新的WindowState被保存到mWindowMap中,键值为IWindow的Bp端。mWindowMap是整个系统所有窗口的一个全集。

2.4 removeWindow

void removeWindow(Session session, IWindow client) {
         synchronized (mGlobalLock) {
                //获取WindowState
             WindowState win = windowForClientLocked(session, client, false);
             if (win != null) {
                 //执行删除
                 win.removeIfPossible();
                 return;
             }
         // Remove embedded window map if the token belongs to an embedded window
         mEmbeddedWindowController.remove(client);
     }
 }

win.removeIfPossible方法和它的名字一样, 并不是直接执行删除操作,而是进行多个条件判断过滤,满足其中一个条件就会return,推迟删除操作。比如View正在运行一个动画,这是就会推迟删除操作直到动画完成。然后调用removeImmediately方法。

3. 事件派发

EventHub:
1.使用inotify监听输入设备的添加和移除;
2.使用epoll机制监听输入设备的数据变化;
3.读取设备文件数据;
4.将原始数据返回给InputReader;

InputReader:不断读取由EventHub监听到的input事件,将多个事件组合成一个可供上层消费的事件(比如将一组触摸事件合并成一个action_down事件),然后交给InputDispatcher进行事件分发;

InputDispatcher:拿到InputReader获取的事件后,对事件进行包装,寻找并分发到目标窗口,对应inputChannel输入;

Android系统是由事件驱动的,而input是常见的事件之一,点击、滑动、长按等操作,都属于input事件,核心类就是InputReader和InputDispatcher;

解释: ViewRootImpl#WindowInputEventReceiver:从下面源码可以看出,此类用于InputChannel输入事件接收以及处理输入事件分发;

    final class WindowInputEventReceiver extends InputEventReceiver {
        //构造方法,接受inputchannel输入事件
         public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
             super(inputChannel, looper);
         }
 
    
    @Override
     public void onInputEvent(InputEvent event) {
        ...
         if (processedEvents != null) {
             if (processedEvents.isEmpty()) {
                 // InputEvent consumed by mInputCompatProcessor
                 finishInputEvent(event, true);
             } else {
                 for (int i = 0; i < processedEvents.size(); i++) {
                    //对输入事件进行分发
                     enqueueInputEvent(
                             processedEvents.get(i), this,
                             QueuedInputEvent.FLAG_MODIFIED_FOR_COMPATIBILITY, true);
                 }
             }
         } else {
             enqueueInputEvent(event, this, 0, true);
         }
     }

ViewRootImpl#InputStage:抽象类,主要用来将事件的处理分成若干个阶段(stage)进行,如果该事件没有被处理,则该stage就会调用onProcess方法处理,然后调用forward执行下一个stage的处理;如果该事件被标识为处理则直接调用forward,执行下一个stage的处理,直到没有下一个stage;

ViewPostImeInputStage:InputStage的子类,将输入事件传递到上层视图;至此,输入事件一层层向上传递,最终交由具体的view进行处理;

如果你还没有掌握Framework,现在想要在最短的时间里吃透它,可以参考一下《Android Framework核心知识点》,里面内容包含了:Init、Zygote、SystemServer、Binder、Handler、AMS、PMS、Launcher……等知识点记录。

《Framework 核心知识点汇总手册》:https://qr18.cn/AQpN4J

Handler 机制实现原理部分:
1.宏观理论分析与Message源码分析
2.MessageQueue的源码分析
3.Looper的源码分析
4.handler的源码分析
5.总结

Binder 原理:
1.学习Binder前必须要了解的知识点
2.ServiceManager中的Binder机制
3.系统服务的注册过程
4.ServiceManager的启动过程
5.系统服务的获取过程
6.Java Binder的初始化
7.Java Binder中系统服务的注册过程

Zygote :

  1. Android系统的启动过程及Zygote的启动过程
  2. 应用进程的启动过程

AMS源码分析 :

  1. Activity生命周期管理
  2. onActivityResult执行过程
  3. AMS中Activity栈管理详解

深入PMS源码:

1.PMS的启动过程和执行流程
2.APK的安装和卸载源码分析
3.PMS中intent-filter的匹配架构

WMS:
1.WMS的诞生
2.WMS的重要成员和Window的添加过程
3.Window的删除过程

《Android Framework学习手册》:https://qr18.cn/AQpN4J

  1. 开机Init 进程
  2. 开机启动 Zygote 进程
  3. 开机启动 SystemServer 进程
  4. Binder 驱动
  5. AMS 的启动过程
  6. PMS 的启动过程
  7. Launcher 的启动过程
  8. Android 四大组件
  9. Android 系统服务 - Input 事件的分发过程
  10. Android 底层渲染 - 屏幕刷新机制源码分析
  11. Android 源码分析实战

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/69477.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习中的批量归一化BN和层归一化LN】BN层(Batch Normalization)和LN层(Layer Normalization)的区别

文章目录 1、概述2、BN层3、LN层4、Pytorch的实现5、BN层和LN层的对比 1、概述 归一化(Normalization) 方法&#xff1a;指的是把不同维度的特征&#xff08;例如序列特征或者图像的特征图等&#xff09;转换为相同或相似的尺度范围内的方法&#xff0c;比如把数据特征映射到[…

如何维护自己的电脑

目录 1、关于电脑选择的建议 1.1、价格预算 1.2、明确需求 1.3、电脑配置 1.4、分辨率 1.5、续航能力 1.6、品牌选择 1.7、用户评测 1.8、各个电商平台对比 1.9、最后决策 2、我的选择 3、电脑保养 3.1 外部清洁 3.2 安装软件 3.3 优化操作系统 3.4 维护硬件设…

TDesign中后台管理系统-用户登录

目录 1 创建用户表2 开发后端接口3 测试接口4 修改登录页面调用后端接口最终效果总结 中后台系统第一个要实现的功能就是登录了&#xff0c;我们通常的逻辑是让用户在登录页面输入用户名和密码&#xff0c;调用后端接口去验证用户的合法性&#xff0c;然后根据接口返回的结果进…

Mac与windows传文件(超过4G且速度超快,非共享)

MAC与Windows文件互传 背景 尝试了网上的一些方法&#xff0c;诸如设置共享文件夹方法等&#xff0c;但是实际使用中感觉效果一般&#xff0c;对于一些小的文件共同编辑速度还可以。但是在备份或者传递一些较大文件或者很多细小文件的时候就有点捉襟见肘了。制作了一个MAC可读…

电力供应这个操作,绝了!

在电力系统中&#xff0c;配电柜扮演着将电能从高压输电线路分配到低压用户终端的重要角色。为了确保电力系统的安全、稳定和高效运行&#xff0c;需要实时监测和管理这些关键设备。这就是配电柜监控系统的价值所在。 配电柜监控系统在电力行业中具有不可替代的作用&#xff0c…

Django项目局域网访问

1、需求 主机运行着Django项目&#xff0c;想要被局域网其它设备访问。 2、解决步骤&#xff08;非常简单&#xff09; 查看本机局域网ip&#xff0c;如&#xff1a;192.168.100.100运行项目&#xff1a;python manage.py runserver 192.168.100.100:8080。 注意这里的地址很…

前端使用ReadableStream.getReader来处理流式渲染

文章目录 前言一、纯css二、vue-typed-js插件1.安装2.注册3.使用总结 三、ReadableStream1.ReadableStream是什么&#xff1f;2.ReadableStream做什么&#xff1f;3.ReadableStream怎么用 前言 需求&#xff1a;让接口返回的文章根据请求一段一段的渲染&#xff0c;同时可以点击…

MySQL8的特性-MySQL8知识详解

MySQL是一个多用户、多线程的SQL数据库服务器。SQL&#xff08;结构化查询语言&#xff09;是世界上最流行和标准化的数据库语言。下面是MySQL的特性。 1、开源性&#xff1a;MySQL是一个开源的关系型数据库管理系统&#xff0c;可以免费使用和修改。 2、可靠性&#xff1a;M…

链表数组OJ题汇总

前言&#xff1a; 在计算机科学中&#xff0c;数组和链表是两种常见的数据结构&#xff0c;用于存储和组织数据。它们分别具有不同的特点和适用场景。 本博客将深入讨论数组和链表在OJ题目中的应用。我们将从基本概念开始&#xff0c;介绍数组和链表的定义和特点&#xff0c;并…

Visual ChatGPT:Microsoft ChatGPT 和 VFM 相结合

推荐&#xff1a;使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 什么是Visual ChatGPT&#xff1f; Visual ChatGPT 是一个包含 Visual Foundation 模型 &#xff08;VFM&#xff09; 的系统&#xff0c;可帮助 ChatGPT 更好地理解、生成和编辑视觉信息。VFM 能够指…

《漫画算法:小灰的算法之旅》——赠书活动

我想应该有很多人对我今天推荐的书籍不陌生&#xff0c;《漫画算法&#xff1a;小灰的算法之旅》已经是圈内人熟知的“红人”了&#xff0c;但也存在不断有新人入坑&#xff0c;这里就好好介绍一下这本包上“糖衣”的算法“炮弹”吧&#xff0c;整个过程如同本书形象“Q弾可爱&…

【css】textarea-通过resize:none 禁止拖动设置大小

使用 resize 属性可防止调整 textareas 的大小&#xff08;禁用右下角的“抓取器”&#xff09;&#xff1a; 没有设置resize:none 代码&#xff1a; <!DOCTYPE html> <html> <head> <style> textarea {width: 100%;height: 150px;padding: 12px 20p…

Android开源 Skeleton 骨架屏

目录 一、简介 二、效果图 三、引用 Skeleton 添加jitpack 仓库 添加依赖: 四、使用 Skeleton 1、VIew 骨架屏使用 ViewSkeletonScreen 2、列表类View 骨架屏 RecyclerViewSkeletonScreen、GridViewSkeletonScreen、 ListViewSkeletonScreen 一、简介 骨架屏的作用是…

【C++】开源:ceres和g2o非线性优化库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍ceres和g2o非线性优化库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&…

极客教程 scrapy和selenium

selenium 极客教程 使用python 调用scrapy的 爬虫Spider并且相互之间可以正常传参实现全局 常规情况创建&#xff0c;使用命令 scrapy genspider baidu "baidu.com"Python中Scrapy框架详解 浏览器调试模式下&#xff08;F12 或 右键检查&#xff09;Command sh…

linux 下 网卡命名改名

Linux 操作系统的网卡设备的传统命名方式是 eth0、eth1、eth2等&#xff0c;而 CentOS7 提供了不同的命名规则&#xff0c;默认是网卡命名会根据网卡的硬件信息&#xff0c;插槽位置等有关&#xff1b;来分配。这样做的优点是命名全自动的、可预知的&#xff0c;缺点是比 eth0、…

【数学】CF1514 C

Problem - 1514C - Codeforces 题意&#xff1a; 思路&#xff1a; Code&#xff1a; #include <bits/stdc.h>using i64 long long;constexpr int N 2e5 10; constexpr int M 2e5 10; constexpr int mod 998244353;void solve() {int n;std::cin >> n;std:…

基于SpringBoot+Vue的地方美食分享网站设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

Tailwind CSS:简洁高效的工具,提升前端开发体验

112. Tailwind CSS&#xff1a;简洁高效的工具&#xff0c;提升前端开发体验 1. 什么是Tailwind CSS&#xff1f; Tailwind CSS是由Adam Wathan、Jonathan Reinink、David Hemphill和Steve Schoger等人共同创建的一种现代CSS框架。与传统的CSS框架不同&#xff0c;Tailwind CS…

OpenEuler 上安装redis服务

访问redis的下载地址 Index of /releases/地址&#xff1a;Index of /releases/ 选择对应的版本。我选择5.0的版本。 下载对应的版本redis wget https://download.redis.io/releases/redis-5.0.8.tar.gz 解压 redis tar -zxvf redis-5.0.9.tar.gz 进入redis目录 cd redis-5…