浅谈View的绘制流程

  • Window:每个Activity都会创建一个Window用于承载View视图的显示,Window是一个抽象类存在了一个唯一实现类PhoneWindow

  • DecorView:最顶层的View,是一个FrameLayout子类,最终会被加载到Window当中,它内部只有一个垂直方向的LinearLayout分为两部分:
    • TitleBar:屏幕顶部的状态栏
    • ContentView:Activity对应的XML布局,通过setContentView设置到DecorView

Activity和Window关联

  • ActivityThread调用scheduleLaunchActivity()
  • scheduleLaunchActivity发送消息sendMessage(H.LAUNCH_ACTIVITY, r);
  • handleLaunchActivity初始化sWindowMannagerService
  • perforLaunchActivity
  • activity.attach
  • new PhoneWindow(this,window) + 将window和windowMangerService绑定:同时,此时完成了window和activity的绑定
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {// Initialize before creating the activityWindowManagerGlobal.initialize();Activity a = performLaunchActivity(r, customIntent);}

Activity和window和view 的关系

activity是系统可视化交互组件,四大组件都由AMS统一管理生命周期,事实上它的职责只是生命周期的管理,处于单一职责的原则,那势必需要将activity和其上的视图View进行解耦,那么久引入window的概念,它是个抽象类,对于activity来说,它的具体实现类是PhoneWindow,在activity执行attach的时候,会创建一个PhoneWindow对象,PhoneWindow作为装载根视图DecorView的顶级容器,activity通过setContentView实际上是调用了PhoneWindow来创建DecorView,并解析xml布局加载到DecorView的contentView部分。

了解Activity中setContentView源码:

public void setContentView(@LayoutRes int layoutResID) {//将xml布局传递到Window当中getWindow().setContentView(layoutResID);initWindowDecorActionBar();
}

从代码可以看出,ActivitysetContentView实质是将View传递到WindowsetContentView()方法中,WindowsetContenView会在内部调用installDecor()方法创建DecorView,看一下它的部分源码: 

 public void setContentView(int layoutResID) { ...............//初始化DecorView以及其内部的contentinstallDecor();//将contentView加载到DecorVoew当中mLayoutInflater.inflate(layoutResID, mContentParent);}private void installDecor() {...............//实例化DecorViewmDecor = generateDecor(-1);mDecor.setWindow(this);//获取ContentmContentParent = generateLayout(mDecor);}protected DecorView generateDecor(int featureId) {...............return new DecorView(context, featureId, this/*PhoneWindow*/, getAttributes());}

通过generateDecor()new一个DecorView,然后调用generateLayout()获取DecorViewcontent,最终通过inflateActivity视图添加到DecorView中的content中,但此时DecorView还未被添加到Window中。添加操作需要借助ViewRootImpl

ViewRootImpl的作用是用来衔接WindowManagerDecorView,在Activity被创建后会通过WindowManagerDecorView添加到PhoneWindow中并且创建ViewRootImpl实例,随后将DecorViewViewRootImpl进行关联,最终通过执行ViewRootImplperformTraversals()开启整个View树的绘制。

绘制过程

对应于ViewRootImpl类,它是连接WindowMannager和DecorView的纽带,View的三大流程均是通过ViewRootImpl完成的,当activity对象被创建完毕后,会将DecorView添加到Window中,同时会创建ViewRootImpl对象,并将ViewRootImpl对象和DecorView建立关联在ViewRootImpl里面performTraversals()方法开始,从最顶层的View(ViewGroup)开始逐层对每个View进行绘制操作,下面来看一下该方法部分源代码:

private void performTraversals() {...............//measur过程performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);//layout过程performLayout(lp, desiredWindowWidth, desiredWindowHeight);//draw过程performDraw();
}

View与window的逻辑结构

对应于ViewRootImpl类,它是连接WindowMannager和DecorView的纽带,View的三大流程均是通过ViewRootImpl完成的,当activity对象被创建完毕后,会将DecorView添加到Window中,同时会创建ViewRootImpl对象,并将ViewRootImpl对象和DecorView建立关联在ViewRootImpl里面performTraversals()分发

Android的View绘制流程是一个复杂的过程,主要包括了几个关键的步骤:Measure(测量)、Layout(布局)、Draw(绘制)。

Measure(测量)

在View的绘制流程中,首先进行的是Measure阶段。这个阶段的主要任务是确定View及其子View的大小和宽高。在源代码中,这个过程主要由onMeasure()方法完成。在这个方法中,我们需要根据MeasureSpec(它表示的是父View希望子View占据的尺寸)来确定子View的尺寸。MeasureSpec是一个int类型,包含了两个部分:大小和模式。大小表示父View希望子View占据的尺寸,模式则表示父View是如何希望我们处理这个尺寸的。

Layout(布局)

测量阶段完成后,View会得到一个大小,然后进入Layout阶段。这个阶段的主要任务是将每个View按照它们在XML文件中定义的布局进行排列。在源代码中,这个过程主要由onLayout()方法完成。在此方法中,我们需要根据View的布局参数(如宽、高、左、上、右、下的margin等)来确定View在屏幕上的具体位置。

Draw(绘制)

Layout阶段完成后,每个View都会被放置在屏幕上的一个具体位置。然后进入Draw阶段,这个阶段的主要任务是将View及其子View的内容绘制到屏幕上。在源代码中,这个过程主要由onDraw()方法完成。在此方法中,我们可以在Canvas上绘制任何我们想要的内容。例如,可以在这个方法中绘制一个背景色、一个文字、一个图片等等。

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

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

相关文章

应用在红外线遥控领域中的心率传感信号接收芯片

红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机和手机系统中。 红外线…

探讨Acrel-1000DP分布式光伏系统的设计与应用-安科瑞 蒋静

摘 要:分布式光伏发电特指在用户场地附近建设,运行方式以用户侧自发自用、余电上网,且在配电系统平衡调节为特征的光伏发电设施,是一种新型的、具有广阔发展前景的发电和能源综合利用方式,它倡导就近发电,就…

mysql 反斜杠\的坑

mysql会对\进行转义,可能导致问题。 mysql数据库中字段存的带有\,比如: name\pojo 在java代码中使用mybatis查询。 如果是等值查询,这样的不需要处理,好像是因为mybaits框架自动把\变为了\ 如果是模糊查询like, 需要把…

视频太大怎么压缩变小?三分钟学会视频压缩

随着科技的不断发展,视频已经成为了我们日常生活中不可或缺的一部分,然而,大尺寸的视频文件常常会给我们带来诸多困扰,例如发送不便、存储空间不足等等,那么,如何将这些过大的视频文件压缩变小呢&#xff1…

新一代开源语音库CoQui TTS冲到了GitHub 20.5k Star

Coqui TTS 项目介绍 Coqui 文本转语音(Text-to-Speech,TTS)是新一代基于深度学习的低资源零样本文本转语音模型,具有合成多种语言语音的能力。该模型能够利用共同学习技术,从各语言的训练资料集转换知识,来…

LNMP创建论坛

lNmp安装: 一、LNMP LNMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整套系统和相关软件, 能够提供动态Web站点服务及其应用开发环境。LNMP是一个缩写词,具体包括Linux操作系统、nginx网站服务器、MySQL数据库服务…

2023年中国熔盐储能装机量、新增装机量及行业投资规模分析[图]

熔盐储能是一种可以传递能量、长时间(6-8h)、大容量储能的技术路径,作为传热介质可以实现太阳能到热能的转换,作为储能介质可以实现将热能和电能的双向转换,可以很好的适应和解决以上两大矛盾。因此,熔盐储…

基于SVM+Webdriver的智能NBA常规赛与季后赛结果预测系统——机器学习算法应用(含python、ipynb工程源码)+所有数据集(一)

目录 前言总体设计系统整体结构图系统流程图 运行环境Python环境Jupyter Notebook环境PyCharm环境MATLAB环境 模块实现1. 数据预处理1)常规赛数据处理2)季后赛数据处理 相关其它博客工程源代码下载其它资料下载 前言 本项目使用了从NBA官方网站获得的数…

ssh 去掉登陆提示

一、ssh链接服务器提示 The authenticity of host cant be established. ECDSA key fingerprint is SHA256:. Are you sure you want to continue connecting (yes/no/[fingerprint])?二、永久解决 | 屏蔽提示 1、打开文件 sudo vi /etc/ssh/ssh_config 2、修改文件内容 …

[Java]0.1+0.2不等于0.3 !!一分钱问题与解决方案

一、原因 原因很简单,计算机存储和计算数组都是用二进制, 而大部分小数转二进制的时候,就丢失精度了。 0.1、0.2、0.3这些小数在二进制里都是循环小数,计算机不可能存储无限循环小数,所以只能截取一部分,导…

中文连续视觉语音识别挑战赛

视觉语音识别,也称唇语识别,是一项通过口唇动作来推断发音内容的技术。该技术在公共安全、助老助残、视频验真等领域具有重要应用。当前,唇语识别的研究方兴未艾,虽然在独立词、短语等识别上取得了长足进展,但在大词表…

从创业者的角度告诉你AI问答机器人网页的重要性

在数字化时代,创业者面临着越来越多的挑战。而AI问答机器人网页正成为创业者们的必备工具。它可以提供即时客户支持、降低运营成本,并实现全天候服务。接下来,我将从创业者的角度阐述一下,AI问答机器人网页为什么那么重要&#xf…

快速自动化处理JavaScript渲染页面的方法

目录 一、使用无头浏览器 二、使用JavaScript渲染引擎 三、使用前端框架工具 随着互联网技术的不断发展,JavaScript已经成为Web开发中不可或缺的一部分。然而,在自动化处理JavaScript渲染页面方面,却常常让开发者感到头疼。本文将介绍一些快…

Nessus已激活,New Scan按钮不可点击

刷新后会给出下面的提示 Plugins are compiling. Nessus will be limited until compilation is complete. 因为插件编译中,所以扫描功能被禁用了。 查看编辑进度,鼠标放到两个循环箭头上即可查看。

6.4 图的存储结构

思维导图: 前言: --- **6.4 图的存储结构** - **核心问题**:由于图的结构复杂性,我们不能仅仅依赖于元素在存储区的物理位置来表示它们之间的关系。 - **邻接矩阵**: - **基本思路**:虽然图没有顺序存…

Junit 单元测试之错误和异常处理

错误和异常处理是测试中非常重要的部分。假设我们有一个服务,该服务从数据库中获取用户。现在,我们要考虑的错误场景是:数据库连接断开。 整体代码示例 首先,为了简化,我们让服务层就是简单的类,然后使用I…

[Machine Learning][Part 6]Cost Function代价函数和梯度正则化

目录 拟合 欠拟合 过拟合 正确的拟合 解决过拟合的方法:正则化 线性回归模型和逻辑回归模型都存在欠拟合和过拟合的情况。 拟合 来自百度的解释: 数据拟合又称曲线拟合,俗称拉曲线,是一种把现有数据透过数学方法来代入一条…

浅谈大数据之Flink-2

1.5 流处理基础概念 在某些场景下,流处理打破了批处理的一些局限。Flink作为一款以流处理见长的大数据引擎,相比其他流处理引擎具有众多优势。本节将对流处理的一些基本概念进行细化,这些概念是入门流处理的必备基础,至此你将正式进入数据流的世界。 1.5.1 延迟和吞吐 …

PHP框架开发实践 | 1024 程序员节:通过index.php找到对应的controller是如何实现的

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师…

STM32CubeMX之DMA辅助串口数据接收

1.DMA辅助串口数据接收 1.1 DMA简介 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。   两个DMA控制器有12个通道(DMA1有7个通道&am…