onMeasure() 方法多次调用的原因

2024-02-28 08:08

本文主要是介绍onMeasure() 方法多次调用的原因,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题引入
某些时候 onMeasure() 会被调用两次,这个问题让我比较困扰,这里我找到了相关源码来解释这个问题。

本文只针对该问题,暂不对其它涉及到的内容分析。

测量的开始
对于 Activity 中 view 的测量,布局,绘制三个过程大部分人都已经比较熟悉了,这里我们直接从一个 Activity 如何开始这三个过程开始找到问题。

第一次测量在什么时候?
那我们需要先知道 ViewRootImpl, 这个类可以理解成它的名字,它是一个 Activity 中所有 View 的 root。

而我们所熟悉的 View 的三板斧以及事件分发就是以它为根节点,向下传递的。但是它本身并不是一个 View,或者说它是实现了一个转接,分发的作用,它的作用性可想而知。

这里直接看 ViewRootImpl 开始测量根部 View (DecorView) 的方法。

performTraversals()
这里节选其中的一部分代码。

performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);// Implementation of weights from WindowManager.LayoutParams
// We just grow the dimensions as needed and re-measure if
// needs be
int width = host.getMeasuredWidth();
int height = host.getMeasuredHeight();
boolean measureAgain = false;if (lp.horizontalWeight > 0.0f) {width += (int) ((mWidth - width) * lp.horizontalWeight);childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,MeasureSpec.EXACTLY);measureAgain = true;
}
if (lp.verticalWeight > 0.0f) {height += (int) ((mHeight - height) * lp.verticalWeight);childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height,MeasureSpec.EXACTLY);measureAgain = true;
}if (measureAgain) {if (DEBUG_LAYOUT) Log.v(mTag,"And hey let's measure once more: width=" + width+ " height=" + height);performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);}


可以看到其中有一个 measureAgain 的标示,以及设置为 true 的两个条件,这里不做额外的篇幅详解,只是简单介绍 verticalWeight 和 horizontalWeight 两个字段的含义。

在第一次 performMeasure() 方法调用后, 如果子View 需要的空间大于父容器为它测量的大小,那么对应的 verticalWeight 和 horizontalWeight 将会大于0,即这两个字段分别对应垂直和水平的情况下子 View 需要的额外空间。

这时候会将 measureAgain 设置为 true, 并且开始第二次测量。

总结
对于不满意父容器测量的子 View, 父容器将会依据 子 View 的测量结果来开始第二次测量。

这篇关于onMeasure() 方法多次调用的原因的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/754898

相关文章

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Mybatis Plus Join使用方法示例详解

《MybatisPlusJoin使用方法示例详解》:本文主要介绍MybatisPlusJoin使用方法示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录1、pom文件2、yaml配置文件3、分页插件4、示例代码:5、测试代码6、和PageHelper结合6

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

SpringBoot读取ZooKeeper(ZK)属性的方法实现

《SpringBoot读取ZooKeeper(ZK)属性的方法实现》本文主要介绍了SpringBoot读取ZooKeeper(ZK)属性的方法实现,强调使用@ConfigurationProperti... 目录1. 在配置文件中定义 ZK 属性application.propertiesapplicati