深入探讨 Android 的 View 显示过程与源码分析

文章目录

    • 1. 探讨 Android 的 View 显示过程
      • 1.1. `onFinishInflate`
      • 1.2. `onAttachedToWindow`
      • 1.3. `onMeasure`
      • 1.4. `onSizeChanged`
      • 1.5. `onLayout`
      • 1.6. `onDraw`
    • 2. 系统代码分析
      • 1.1. `onFinishInflate`
      • 1.2. `onAttachedToWindow`
      • 1.3. `onMeasure`
      • 1.4. `onSizeChanged`
      • 1.5. `onLayout`
      • 1.6. `onDraw`
    • 3. 视图显示过程总结
    • 4. 优化和性能考虑
    • 5. 结论
    • 6. 进一步深入探讨 Android 的 View 显示过程
      • 6.1. `onFinishInflate`
      • 6.2. `onAttachedToWindow`
      • 6.3. `onMeasure`
      • 6.4. `onSizeChanged`
      • 6.5. `onLayout`
      • 6.6. `onDraw`
    • 7. 视图显示过程总结(续)

1. 探讨 Android 的 View 显示过程

在 Android 中,View 的显示过程涉及多个步骤和方法,从底层到上层依次执行。理解这些步骤和方法对优化 UI 性能和实现复杂的自定义 View 非常重要。

1.1. onFinishInflate

当一个 View 从 XML 布局文件中被加载并完成所有子 View 的初始化时,onFinishInflate 方法被调用。这个方法在整个布局层次结构被完全创建之后调用,可以在这里进行一些额外的初始化工作。

@Override
protected void onFinishInflate() {super.onFinishInflate();// 视图和子视图的初始化工作
}

1.2. onAttachedToWindow

当一个 View 被附加到一个窗口时,onAttachedToWindow 方法被调用。在这个方法中,可以进行一些与窗口相关的初始化工作,例如启动动画、设置监听器等。

@Override
protected void onAttachedToWindow() {super.onAttachedToWindow();// 视图附加到窗口后的操作
}

1.3. onMeasure

onMeasure 方法用于测量 View 的大小。这个方法在布局过程中多次调用,用于确定每个 View 的宽度和高度。自定义 View 时,通常需要重写这个方法以处理特定的测量需求。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(width, height);
}

1.4. onSizeChanged

当 View 的大小发生变化时,onSizeChanged 方法被调用。这通常发生在 View 的初次布局和大小调整时。在这个方法中,可以根据新的大小进行调整。

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);// 视图大小改变后的操作
}

1.5. onLayout

onLayout 方法用于为 View 的所有子 View 安置位置。这个方法在布局过程中调用,用于确定子 View 的位置。

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);// 布局子视图的位置int childLeft = 0;int childTop = 0;for (int i = 0; i < getChildCount(); i++) {View child = getChildAt(i);child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight());childTop += child.getMeasuredHeight();}
}

1.6. onDraw

onDraw 方法用于绘制 View 的内容。在这个方法中,可以使用 Canvas 对象进行绘制操作,例如绘制文本、图形等。自定义 View 时,通常需要重写这个方法以实现特定的绘制需求。

@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);// 自定义绘制操作Paint paint = new Paint();paint.setColor(Color.RED);canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
}

2. 系统代码分析

1.1. onFinishInflate

ViewGroup 类中,当所有的子 View 都被加载并添加到父 View 时,onFinishInflate 方法被调用。它确保了布局的完整性和一致性。

1.2. onAttachedToWindow

onAttachedToWindow 方法在 View 的 ViewRootImpl 被创建并与窗口关联时调用。它确保 View 可以访问窗口相关的资源和服务。

1.3. onMeasure

onMeasure 方法是 View 类中的一个核心方法,它通过 MeasureSpec 参数来计算 View 的大小。MeasureSpec 包含测量模式和尺寸信息。

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);// 自定义测量逻辑
}

1.4. onSizeChanged

onSizeChanged 方法在 View 类中实现,用于处理 View 大小的变化。它提供了新旧尺寸的信息,以便在大小变化时进行相应的调整。

1.5. onLayout

onLayout 方法在 ViewGroup 类中实现,用于布置子 View 的位置。它通过遍历子 View 并调用每个子 View 的 layout 方法来实现布局。

1.6. onDraw

onDraw 方法在 View 类中实现,用于绘制 View 的内容。Canvas 对象提供了一系列绘制方法,可以在 onDraw 方法中调用这些方法进行自定义绘制。

3. 视图显示过程总结

  1. 视图加载和初始化

    • XML 布局文件被解析并创建 View 实例。
    • onFinishInflate 方法被调用,完成视图和子视图的初始化。
  2. 视图附加到窗口

    • 当 View 被添加到窗口时,onAttachedToWindow 方法被调用。
    • 可以在此方法中进行与窗口相关的初始化工作。
  3. 测量视图

    • 在布局过程中,onMeasure 方法被调用,用于测量 View 的大小。
    • 通过 MeasureSpec 参数来确定 View 的测量模式和尺寸。
  4. 视图大小变化

    • 当 View 的大小发生变化时,onSizeChanged 方法被调用。
    • 可以在此方法中根据新的大小进行调整。
  5. 布局子视图

    • 在布局过程中,onLayout 方法被调用,用于布置子 View 的位置。
    • 通过遍历子 View 并调用每个子 View 的 layout 方法来实现布局。
  6. 绘制视图

    • 在绘制过程中,onDraw 方法被调用,用于绘制 View 的内容。
    • 可以在 onDraw 方法中使用 Canvas 对象进行自定义绘制。

4. 优化和性能考虑

  • 视图层次结构优化:避免过深的视图层次结构,尽量减少布局嵌套。
  • 异步任务:避免在主线程中执行耗时操作,使用异步任务处理。
  • 内存管理:及时释放不再需要的资源,避免内存泄漏。

5. 结论

通过深入理解和合理使用 Android 中的 View 显示过程,可以构建出高效、稳定且用户体验良好的应用程序。掌握这些关键技术和设计模式,不仅可以提高开发效率,还能显著提升应用的整体质量。在实际开发中,灵活应用这些技术,结合实际需求进行优化和调整,是构建优秀 Android 应用的基础。

6. 进一步深入探讨 Android 的 View 显示过程

为了更好地理解 Android View 的显示过程,我们需要深入分析系统源码中的具体实现。以下是一些关键方法在系统源码中的详细说明。

6.1. onFinishInflate

ViewGroup.java 中,onFinishInflate 方法的定义如下:

protected void onFinishInflate() {// This is called after a view and all of its children has been inflated
}

这个方法被调用时,整个布局树已经被完全构建,可以在此处进行一些额外的初始化工作。

6.2. onAttachedToWindow

View.java 中,onAttachedToWindow 方法的定义如下:

protected void onAttachedToWindow() {mAttachInfo = mParent.getViewRootImpl().mAttachInfo;if (mOverlay != null) {mOverlay.getOverlayView().dispatchAttachedToWindow(mAttachInfo, mWindowAttachCount);}onVisibilityAggregated(isAggregatedVisible());if ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) != 0) {refreshDrawableState();}// Additional operations when the view is attached to the window
}

这个方法确保了 View 能够访问与窗口相关的资源和服务。

6.3. onMeasure

onMeasure 方法在 View.java 中的实现如下:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);// Measure the view dimensionsint width;int height;if (widthMode == MeasureSpec.EXACTLY) {width = widthSize;} else {// Measure the width based on the content and paddingwidth = computeWidth();}if (heightMode == MeasureSpec.EXACTLY) {height = heightSize;} else {// Measure the height based on the content and paddingheight = computeHeight();}setMeasuredDimension(width, height);
}

onMeasure 方法通过 MeasureSpec 参数确定 View 的测量模式和尺寸。

6.4. onSizeChanged

onSizeChanged 方法在 View.java 中的实现如下:

protected void onSizeChanged(int w, int h, int oldw, int oldh) {// Handle the size changeif (w != oldw || h != oldh) {// Perform any operations needed when the size changes}
}

这个方法提供了新旧尺寸的信息,以便在大小变化时进行相应的调整。

6.5. onLayout

onLayout 方法在 ViewGroup.java 中的实现如下:

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {int count = getChildCount();for (int i = 0; i < count; i++) {View child = getChildAt(i);if (child.getVisibility() != GONE) {int childLeft = // Calculate the child's left positionint childTop = // Calculate the child's top positionchild.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight());}}
}

onLayout 方法遍历子 View 并调用每个子 View 的 layout 方法来实现布局。

6.6. onDraw

onDraw 方法在 View.java 中的实现如下:

protected void onDraw(Canvas canvas) {// Perform custom drawing operationsPaint paint = new Paint();paint.setColor(Color.RED);canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
}

onDraw 方法使用 Canvas 对象进行自定义绘制。

7. 视图显示过程总结(续)

  1. 视图加载和初始化

    • 解析 XML 布局文件并创建 View 实例。
    • 调用 onFinishInflate 方法,完成视图和子视图的初始化。
  2. 视图附加到窗口

    • View 被添加到窗口时调用 onAttachedToWindow 方法。
    • 进行与窗口相关的初始化工作。
  3. 测量视图

    • 布局过程中调用 onMeasure 方法测量 View 的大小。
    • 使用 MeasureSpec 参数确定测量模式和尺寸。
  4. 视图大小变化

    • View 大小变化时调用 onSizeChanged 方法。
    • 根据新的大小进行调整。
  5. 布局子视图

    • 布局过程中调用 onLayout 方法布置子 View 的位置。
    • 遍历子 View 并调用每个子 View 的 layout 方法实现布局。
  6. 绘制视图

    • 绘制过程中调用 onDraw 方法绘制 View 的内容。
    • 使用 Canvas 对象进行自定义绘制。
欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力

在这里插入图片描述

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

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

相关文章

数字化浪潮中的TPM革新:打造高效生产新范式

在数字化浪潮席卷全球的今天&#xff0c;传统生产管理模式正面临前所未有的挑战与机遇。TPM&#xff08;全面生产维护&#xff09;作为一种先进的生产管理理念&#xff0c;如何在数字化驱动下焕发新的活力&#xff0c;成为制造业转型升级的关键一环。 数字化技术为TPM带来了前…

探秘Flask中的表单数据处理

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、Flask中的表单处理机制 三、Flask表单处理实战 四、处理表单数据的注意事项…

为什么要使用动态代理IP?

一、什么是动态代理IP&#xff1f; 动态代理IP是指利用代理服务器来转发网络请求&#xff0c;并通过不断更新IP地址来保护访问者的原始IP&#xff0c;从而达到匿名访问、保护隐私和提高访问安全性的目的。动态代理IP在多个领域中都有广泛的应用&#xff0c;能够帮助用户…

vue路由跳转之【编程式导航与传参】

vue路由有两种跳转方式 ----> 编程式与声明式&#xff0c;本文重点讲解vue路由的【编程式导航 】【编程式导航传参 ( 查询参数传参 & 动态路由传参 ) 】等内容&#xff0c;并结合具体案例让小伙伴们深入理解 &#xff0c;彻底掌握&#xff01;创作不易&#xff0c;需要的…

2023年全球DDoS攻击现状与趋势分析

天翼安全科技有限公司副总工程师、运营保障部总经理陈林表示&#xff0c;2023年扫段攻击频次快速增长&#xff0c;成为网络基础设施面临的最大威胁。为躲避防御&#xff0c;低速扫段攻击成为主流达到攻击总数的73.19%&#xff1b;43.26%的C段攻击持续时间小于5分钟&#xff0c;…

Linux中部署MinIO

Linux中部署MinIO 下载MinIO可执行程序&#xff1a; wget https://dl.min.io/server/minio/release/linux-amd64/minio 添加执行权限&#xff1a; chmod x minio 创建存储目录&#xff0c;例如/data&#xff1a; mkdir -p /data 运行MinIO服务器&#xff0c;需要设置MIN…

【设计模式】JAVA Design Patterns——Factory Method(虚拟构造器模式)

&#x1f50d;目的 为创建一个对象定义一个接口&#xff0c;但是让子类决定实例化哪个类。工厂方法允许类将实例化延迟到子类 &#x1f50d;解释 真实世界例子 铁匠生产武器。精灵需要精灵武器&#xff0c;而兽人需要兽人武器。根据客户来召唤正确类型的铁匠。 通俗描述 它为类…

三维前端项目中用THREEWebGLRenderer于创建渲染器对象

在三维前端项目开发中&#xff0c;可以使用THREE.WebGLRenderer创建渲染器对象。艾斯视觉作为行业ui设计与前端开发服务商很高兴能在这里与你共同探讨&#xff1a;THREE.WebGLRenderer是 Three.js 库中用于将 3D 场景渲染到屏幕上的类。以下是一个示例代码&#xff0c;展示了如…

element中table的selection-change监听改变的那条数据的下标

<el-table ref"table" :loading"loading" :data"tableData" selection-change"handleSelectionChange"></el-table>当绑定方法selection-change&#xff0c;当选择项发生变化时会触发该事件 // 多选框选中数据handleSele…

truncate IDL_UB1$导致数据库open hang---惜分飞

在一次数据库恢复中,发现IDL_UB1$表被truncate,然后数据库在open过程中会hang住,而且不报任何错误,这里通过试验进行重现.对于这类问题,以前有过类似处理测试&#xff1a;truncate IDL_UB1$恢复试验数据库版本 SQL> select * from v$version; BANNER ---------------------…

vivado原语使用

首先介绍一下原语&#xff1a;其英文名字为Primitive。原语是Xilinx针对其器件特征开发的一系列常用模块的名字&#xff0c;用户可以将其看成Xilinx公司为用户提供的ip&#xff0c;是芯片中的基本元件&#xff0c;代表FPGA中实际拥有的硬件逻辑单元&#xff0c;如LUT&#xff0…

汇编:x86汇编环境搭建与基础框架(32位)

32位汇编代码编写环境&#xff1a;Visual Studio&#xff08;笔者用的版本为2017&#xff09;&#xff1b;先来说一下在Visual Studio 2017中编写汇编代码的准备操作&#xff1a; ①创建空项目 ②设置项目属性&#xff1a;平台工具集设置为Visual Studio 2015(v140)&#xff0…

YOLOv5改进 | 注意力机制 | 添加三重注意力机制 TripletAttention【原理 + 完整代码】

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 得益于在通道或空间位置之间建立相互依赖关系的能力&#xff0c;近年来&#xff0c;注意力机制在计算机视觉任务中得到了广泛的研究和应用。…

嵌入式Linux命令基础

一、命令概述 1. 命令本质 命令的特性&#xff1a;一般就是对应shell命令&#xff0c;每一个命令代表一个可执行程序&#xff0c;运行一个命令就相当于 运行一个可执行代码。 2. 打开终端方法 第一种方法&#xff1a;通过鼠标右键选择打开终端 第二种方法&#xff1a;利用…

Django——Admin站点(Python)

#前言&#xff1a; 该博客为小编Django基础知识操作博客的最后一篇&#xff0c;主要讲解了关于Admin站点的一些基本操作&#xff0c;小编会继续尽力更新一些优质文章&#xff0c;同时欢迎大家点赞和收藏&#xff0c;也欢迎大家关注等待后续文章。 一、简介&#xff1a; Djan…

认识Oracle v$mystat视图

v$mystat就是当前用户的各种统计信息&#xff0c; sid就是session的id(也就是当前用户),STATISTIC#就是统计量的编号(用来唯一确定统计量的名称)&#xff0c;value是统计量的值&#xff1b; desc命令在Oracle中通常用于查看表结构&#xff1b; v$mystat视图中只会有当前用户…

【NVM】nvm常用命令,切换node版本命令

nvm常用的命令&#xff0c;切换node版本命令 nvm 查看支持安装的node版本 nvm list available nvm安装指定版本node nvm install 版本号 例如&#xff1a;nvm install 10.24.1 nvm查看本机安装所有node版本 nvm list nvm切换node版本 nvm use 10.24.1 检测当前node版本 node -…

大数据中的电商数仓项目:探秘业务的核心

我学习完一个电商数仓的项目和电影实时推荐项目&#xff0c;便兴冲冲的去面试大数据开发岗&#xff0c;在面试的时候&#xff0c;面试官总是喜欢问&#xff0c;聊聊你为什么要做这个项目以及你这个项目有哪些业务&#xff1f; 我心想&#xff0c;为什么要做这个业务&#xff1f…

【码银送书第二十期】《游戏运营与出海实战:策略、方法与技巧》

市面上的游戏品种繁杂&#xff0c;琳琅满目&#xff0c;它们是如何在历史的长河中逐步演变成今天的模式的呢&#xff1f;接下来&#xff0c;我们先回顾游戏的发展史&#xff0c;然后按照时间轴来叙述游戏运营的兴起。 作者&#xff1a;艾小米 本文经机械工业出版社授权转载&a…

用Idea 解决Git冲突

https://intellijidea.com.cn/help/idea/resolving-conflicts.html https://www.jetbrains.com/help/idea/resolve-conflicts.html idea 官方文档 当您在团队中工作时&#xff0c;您可能会遇到这样的情况:有人对您当前正在处理的文件进行更改。如果这些更改没有重叠(也就是说…