Android Framework学习二:Activity创建及View绘制流程

文章目录

  • Window绘制流程
    • Window Manager Service(WMS)
    • Surface
    • SurfaceFlinger
  • 安卓View层次结构
    • Activity
    • PhoneWindow
    • Activity与PhoneWindow两者之间的关系
    • ViewRootImpl
    • DecorView
      • DecorView 的作用
      • DecorView 的结构
      • 总结
  • Activity创建流程
  • View invalidate调用流程

Window绘制流程

在这里插入图片描述
在安卓系统中,Window Manager Service(WMS)和 Surface 是与窗口管理和图形显示相关的重要概念。

Window Manager Service(WMS)

  • 功能概述:WMS 是安卓系统中负责管理窗口的系统服务。它主要负责窗口的创建、销毁、布局、显示顺序以及与用户交互等方面的管理。
  • 工作原理:当一个应用程序创建一个窗口(例如 Activity 的界面)时,它会向 WMS 发送请求。WMS 会为该窗口分配一个唯一的标识,并根据窗口的属性(如大小、位置、层级等)将其添加到窗口管理列表中。在绘制窗口时,WMS 会协调各个窗口的位置和显示顺序,确保它们按照正确的方式显示在屏幕上。当用户进行触摸屏幕等交互操作时,WMS 会根据触摸事件的位置和窗口的布局,将事件分发给相应的窗口进行处理。

Surface

  • 概念:Surface 是安卓图形系统中的一个重要概念,它代表了一个可绘制的区域,用于在屏幕上显示图形内容。可以将 Surface 看作是一块画布,应用程序可以在上面绘制各种图形、图像和文本等内容。
  • 作用:每个窗口都有一个或多个 Surface 与之关联。当应用程序需要绘制窗口的内容时,它会通过 Surface 来获取绘图的上下文,然后使用图形库(如 OpenGL)在 Surface 上进行绘制。绘制完成后,Surface 会将绘制的结果提交给系统的图形合成器(通常是 Surface Flinger),由图形合成器将各个窗口的 Surface 进行合成,最终显示在屏幕上。
  • 与 WMS 的关系:WMS 负责管理窗口的整体布局和显示顺序,而 Surface 则是窗口内容绘制的载体。WMS 会根据窗口的状态和用户的操作,通知应用程序更新其 Surface 的内容。例如,当窗口大小发生变化时,WMS 会通知应用程序重新绘制 Surface 以适应新的大小。同时,WMS 也会与 Surface Flinger 协作,确保各个 Surface 能够按照正确的顺序和方式进行合成和显示。

SurfaceFlinger

SurfaceFlinger是 Android 系统中的一个关键服务,主要负责将不同应用程序的 2D、3D surface 进行组合,并将最终合成的图像发送到显示设备进行显示。

安卓View层次结构

Activity包含PhoneWindow、DecorView、ViewRootImpl等
在这里插入图片描述

Activity

Activity属于安卓应用程序的四大组件之一,它为用户提供了一个可视化的界面,让用户能够与应用进行交互。每一个Activity都代表着一个屏幕画面,像是登录界面、主界面等。
在安卓中,Activity是由ActivityManagerService(AMS,活动管理器服务) 创建的 。
以下是Activity的一个简单示例:

import android.app.Activity;
import android.os.Bundle;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}
}

PhoneWindow

PhoneWindow是Window类的具体实现,Window类在安卓系统里代表着一个顶级的视觉容器,它负责管理窗口的样式、背景以及标题栏等。PhoneWindow主要处理窗口的具体显示逻辑,例如设置窗口的背景、标题栏、内容视图等。

Activity与PhoneWindow两者之间的关系

  • 包含关系:Activity包含一个PhoneWindow对象,在Activity的创建过程中,会默认创建一个PhoneWindow对象。
  • 视图关联:Activity通过PhoneWindow来设置和管理其视图。Activity的setContentView()方法实际上是调用了PhoneWindow的setContentView()方法。
// Activity类中的setContentView方法
@Override
public void setContentView(@LayoutRes int layoutResID) {getWindow().setContentView(layoutResID);initWindowDecorActionBar();
}

Activity是用户交互的界面载体,负责处理用户的操作和业务逻辑;PhoneWindow则是窗口的具体实现,负责窗口的显示和管理。它们紧密协作,共同构成了安卓应用程序的用户界面。

ViewRootImpl

  • 概述:ViewRootImpl是View与WindowManager之间的桥梁,它不是一个真正的View,但它管理着一个View树的根节点,在Android系统中,每个Window都对应着一个ViewRootImpl实例。
    作用
  • 视图绘制管理:负责协调View树的绘制过程,包括测量(measure)、布局(layout)和绘制(draw)三个阶段。它会根据屏幕的刷新频率,通过Choreographer来触发视图的重绘,确保界面能够及时更新。
  • 事件分发:接收系统传递的输入事件,如触摸事件、按键事件等,并将这些事件分发给View树中的各个View进行处理。它是事件从系统到应用View的重要传递环节。
  • 与窗口管理器交互:与WindowManagerService(WMS)进行通信,负责处理窗口的创建、销毁、大小调整等操作。例如,当Activity启动时,ViewRootImpl会与WMS交互来创建窗口,并将DecorView添加到窗口中。

DecorView

在 Android 系统中,DecorView 是窗口(Window)的最顶层视图(顶级 ViewGroup),它作为整个窗口的根视图,包含了系统的装饰(如状态栏、导航栏)和应用程序的内容视图(如 Activity 的布局)。

DecorView 的作用

  • 窗口的根容器:每个 Activity 的窗口(PhoneWindow)都包含一个 DecorView,它是 View 层级的最顶层。
  • 管理系统 UI:DecorView 负责处理系统窗口装饰(如状态栏、ActionBar/Toolbar)和应用程序内容的协调。
  • 内容视图的父容器:开发者通过 setContentView() 设置的布局会被添加到 DecorView 的一个子 ViewGroup(通常是 FrameLayout,ID 为 android.R.id.content)中。

DecorView 的结构

DecorView是每个Activity界面的顶层视图,它是一个FrameLayout。
DecorView 通常包含以下两部分:

  • 系统装饰部分
    状态栏(Status Bar)、导航栏(Navigation Bar)等系统 UI。
    由主题(Theme)控制是否显示(如全屏模式会隐藏系统装饰)。
  • 应用内容部分
    通过 setContentView() 设置的布局会被添加到 android.R.id.content 这个子 FrameLayout 中。

总结

DecorView 是 Android 窗口系统的核心组件,作为连接系统 UI 和应用内容的桥梁。理解它的结构和功能有助于处理全屏、键盘交互、窗口属性等高级场景。实际开发中,通常只需通过 setContentView() 操作内容部分,而无需直接操作 DecorView。

Activity创建流程

Activity中AMS创建的。
在这里插入图片描述

  • window的初始化是在 Acticity 创建的时候初始化, 在Acticity对象创建后,会调用attach方法,Windows对象就是这个时候创建的。
  • Activity的setContentView其实调用的是PhoneWindow的setContentView。
  • setContentView中调用installDecor()进行DecorView的初始化。
  • onResume中会调用WindowMangerImpl的addView, ViewRootImpl就是在这个addView中创建的。
  • addView会调用ViewRootImpl的setView,setView调用WMS的addView并调用requestLayout。
  • requestLayout调用scheduleTraversals(会创建surface),scheduleTraversals调用见下段invalidate流程后段会有讲到主要是调用measure,layout,draw。

如下图为addView流程
在这里插入图片描述

View invalidate调用流程

在这里插入图片描述

  1. 起始调用
    当我们希望重绘某个View时,直接调用其invalidate方法 。比如在自定义View的事件处理方法(如onClick) 或者数据更新逻辑中调用。invalidate方法会转而调用invalidate(true) ,这里的参数表示是否同时使绘图缓存无效,一般全量刷新时为true。
  2. invalidateInternal方法
    invalidate(true)会调用invalidateInternal方法,此方法会进行以下操作:
    判断是否需要重绘:调用skipInvalidate方法判断该View是否不需要重绘,不需要重绘的条件是该View不可见并且未进行动画。
  • 处理重绘标志位:进一步判断View是否需要绘制,如判断表达式(mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ,若满足重绘条件,则处理相关标志位,将当前View标记为 “脏” ,即设置mPrivateFlags中的相关标志,表明该View需要重绘。
  • 确定重绘区域:对于开启硬件加速的应用程序,调用父视图的invalidateChild函数绘制整个区域;否则只绘制指定的dirty区域(r变量所指区域)。这是一个向上回溯的过程,每一层的父View都将自己的显示区域与传入的刷新Rect做交集。
  1. ViewGroup中的调用
  • invalidateChild方法:在ViewGroup中,invalidateChild方法会从当前的布局View向上不断遍历其父布局。它会先处理子View重绘相关逻辑,比如根据子View情况设置一些标志位,然后调用父布局的invalidateChildInParent方法。
  • invalidateChildInParent方法:该方法会计算需要重绘的区域 ,涉及到location数组(表示自身左边、上边距离父组件的距离,确立在坐标系的相对位置 )和dirty矩形(包含自身宽高,确立需要重绘的面积大小 )。计算后会继续向上请求父布局重绘,直到父布局为ViewRootImpl 。
  1. ViewRootImpl中的处理
  • invalidateChildInParent方法:ViewRootImpl中的invalidateChildInParent方法会检查线程是否正确 ,若dirty为null,表示要重绘整个区域,直接调用invalidate;若dirty为空且没有动画,就不需要重绘,直接返回。否则会对重绘区域进行进一步处理,如根据滚动偏移等情况调整区域。
  • invalidate方法:调用invalidate方法后,会通过scheduleTraversals方法安排一次视图遍历。
  1. 视图遍历与绘制
  • scheduleTraversals方法:安排视图遍历工作,将任务添加到消息队列,待合适时机(比如下一次绘制周期 )执行。
  • performTraversals方法:视图遍历的核心方法,依次执行测量(performMeasure ,调用measure ,最终到onMeasure )、布局(performLayout ,调用layout ,最终到onLayout )、绘制(performDraw ,调用draw ,最终到onDraw )等步骤 ,完成整个View树的更新绘制 。其中performDraw会进一步调用drawSoftware ,最终触发View的draw方法,开始实际绘制。
    在这里插入图片描述
    Android Framework学习一:系统框架、启动过程
    Android Framework学习二:Activity创建及View绘制流程
    作者:帅得不敢出门

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于ssm的智慧养老平台(全套)

一、系统架构 前端:jsp | js | jquery | css 后端:spring | springmvc | mybatis 环境:jdk1.8 | mysql | maven | tomcat 二、代码及数据库 三、功能介绍 01. 登录 02. 管理员-主页 03. 管理员-个人中心 04. 管理员-…

计算机视觉技术的发展历程

计算机视觉技术的发展历程可以分为以下几个阶段: 早期探索阶段(1960s-1980s) 1960年代:计算机视觉的概念开始形成,研究者尝试让计算机识别和理解图像,主要集中在基础的图像处理,如边缘检测和特…

2025五一杯B题五一杯数学建模思路代码文章教学: 矿山数据处理问题

完整内容请看文章最下面的推广群 问题1. 根据附件1中的数据和,建立数学模型,对数据A进行某种变换,使得变换后的结果与数据尽可能接近。计算变换后的结果与数据的误差,并分析误差的来源(如数据噪声、模型偏差等&#xf…

.NET 平台详解

什么是 .NET? .NET 是一个由微软开发的跨平台、开源的开发者平台,用于构建多种类型的应用程序。它提供了一致的编程模型和丰富的类库,支持多种编程语言(如 C#、F#、Visual Basic)。 .NET 的核心组成 运行时环境 CLR …

ICRA 2025 基于触觉反馈的闭环分层控制框架——开放环境下通用门开启的智能规划与操作

在机器人领域,让机器人在开放环境中与日常物品交互一直是个难题,其中开门任务极具挑战性。门的设计、机械结构和推拉方式多种多样,现有方法存在诸多局限。基于运动学的方法依赖已知门模型,面对未知门时难以发挥作用;几…

阿里云服务迁移实战: 07-其他服务迁移

概述 当完成了服务器、数据库、IP、OSS等迁移后,剩下的就是其他服务了。 短信网关 短信模板只能一个个创建,不能批量操作。但是可以使用以下方式优化操作。 在原账号导出模板列表 概述 当完成了服务器、数据库、IP、OSS等迁移后,剩下的…

(六——下)RestAPI 毛子(Http resilience/Refit/游标分页/异步大文件上传)

文章目录 项目地址一、Refit1.1 安装需要的包1.2 创建接口IGitHubApi1.3 创建RefitGitHubService1. 实现接口2. 注册服务 1.4 修改使用方法 二、Http resilience2.1 安装所需要的包2.2 创建resilience pipeline简单版2.3 创建全局的resilience处理1. 创建清理全局ResilienceHan…

leetcode 977. Squares of a Sorted Array

题目描述 双指针法一 用right表示原数组中负数和非负数的分界线。 nums[0,right-1]的是负数&#xff0c;nums[right,nums.size()-1]是非负数。 然后用合并两个有序数组的方法。合并即可。 class Solution { public:vector<int> sortedSquares(vector<int>&…

在 API 模拟阶段:Apipost vs. Faker.js vs. Postman —— 为什么 Apipost 是最优选择

在构建 API 的过程中&#xff0c;模拟数据的能力至关重要。就像你在做饭时等待食材送达一样——没有原料&#xff0c;菜也没法完成。 但是&#xff0c;当你的后端还在开发中&#xff0c;而前端又急需真实的 API 响应进行开发时&#xff0c;该怎么办&#xff1f;这时候&#xf…

一种快速计算OTA PSRR的方法(Ⅰ)

序言:最近碰到了一道有趣的习题&#xff0c;让我重新思考了下如何计算运放的PSRR&#xff0c;再结合相关论文&#xff0c;现将所思所想分享出来&#xff0c;欢迎大家讨论。 1.从Razavi的一道习题引入 题目要求计算电路的PSRR&#xff0c;已知PSRR定义为信号增益除以电源增益&am…

第十二届蓝桥杯 2021 C/C++组 空间

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; 思路详解&#xff1a; 代码&#xff1a; 代码详解&#xff1a; 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 空间 - 蓝桥云课 思路&#xff1a; 思路详解&#…

TensorFlow深度学习实战——基于循环神经网络的情感分析模型

TensorFlow深度学习实战——基于循环神经网络的情感分析模型 0. 前言1. 数据处理2. 模型构建与训练3. 模型评估相关链接 0. 前言 情感分析 (Sentiment Analysis) 是自然语言处理中的一项技术&#xff0c;旨在识别和提取文本中的情感信息&#xff0c;通常是分析一段文本中是否存…

eslint相关报错收集

[vue/no-multiple-template-root]The template root requires exactly one element.eslint-plugin-vuejsx报错&#xff1a;jsx报错Parsing error: Unexpected token &#xff1c;eslint&#xff1b;ts报错&#xff1a;Parsing error: Unexpected token {eslintmodule报错 ‘mod…

【论文推荐】深度学习赋能地质灾害分析:数据、模型、应用与机遇(用于地质灾害分析的深度学习:数据源)

【论文推荐】深度学习赋能地质灾害分析&#xff1a;数据、模型、应用与机遇&#xff08;用于地质灾害分析的深度学习&#xff1a;数据源&#xff09; 【论文推荐】深度学习赋能地质灾害分析&#xff1a;数据、模型、应用与机遇&#xff08;用于地质灾害分析的深度学习&#xf…

判断用户选择的Excel单元格区域是否跨页?

VBA应用程序开发过程中&#xff0c;经常需要处理用户选中的单元格区域&#xff0c;有的应用场景中&#xff0c;需要限制用户选中区域位于同一页中&#xff08;以打印预览显示的分页划分&#xff09;&#xff0c;但是VBA对象模型中并没有提供相应的接口&#xff0c;用于快速查询…

题解:洛谷 CF2091E Interesting Ratio

思路推导 我们先对 32 32 32 和 96 96 96 进行二进制拆分。 相同部分&#xff08;用 α \alpha α 表示&#xff09;&#xff1a; 5 5 5 个 2 2 2。 不同部分&#xff08;用 β \beta β 表示&#xff09;&#xff1a; 1 1 1 和 3 3 3。 gcd ⁡ ( 32 , 96 ) \gcd(32,9…

linux安装配置PostgreSQL

环境&#xff1a;centos7、SpringBoot、PostgreSQL15 PostgreSQL: Linux downloads (Red Hat family) PostgreSQL安装 1.安装 PostgreSQL Yum 仓库 RPM 包 sudo rpm -ivh https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noar…

docker安装jenkins v2.504.1集群

1 概述 Jenkins是一款开源的、基于Java开发的持续集成&#xff08;CI&#xff09;与持续交付&#xff08;CD&#xff09;工具&#xff0c;旨在通过自动化构建、测试和部署流程&#xff0c;提升软件开发效率与质量。 ‌ 1.1 核心功能与特点 持续集成与交付‌ Jenkins支持自动化…

5月2日日记

今天看了爸爸推荐的书&#xff0c;叫&#xff1a;“高效能人士的七个习惯” 现在刚看完50页&#xff0c;感觉确实有点东西&#xff0c; 七个习惯分别是&#xff1a; 个人层面1积极主动 2要事第一 3以终为始 社交层面 4知彼解己5 统效综合 6双赢思维 7不断更新 目前还没有…

Aws S3上传优化

上传大约 3.4GB 的 JSON 文件&#xff0c;zip算法压缩后约为 395MB&#xff0c;上传至 S3 效率优化&#xff0c;有一些优化方案可以提高上传速率。下面是几种可能的优化方式&#xff0c;包括选择压缩算法、调整上传方式、以及其他可能的方案。 方案 1. 选择更好的压缩算法 压…