Android:requestLayout、invalidate 和 postInvalidate 的区别

提醒:下面源码来自SDK里Android-34版本

一、requestLayout

点击查看requestLayout官网文档

1.1 requestLayout方法源码
 /*** Call this when something has changed which has invalidated the* layout of this view. This will schedule a layout pass of the view* tree. This should not be called while the view hierarchy is currently in a layout* pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the* end of the current layout pass (and then layout will run again) or after the current* frame is drawn and the next layout occurs.** <p>Subclasses which override this method should call the superclass method to* handle possible request-during-layout errors correctly.</p>* 上面翻译* 当某些东西发生改变使。无效时调用这个* 这个视图的布局。这将安排视图的布局传递树。* 当视图层次结构当前处于布局时,不应该调用这个函数* pass ({@link #isInLayout()})。如果正在进行布局,* 请求可能会在结束当前布局传递(然后布局将再次运行)* 或在当前绘制框架,并发生下一个布局。* * 重写此方法的子类应该调用父类方法正确处理布局期间可能出现的请求错误。*/@CallSuperpublic void requestLayout() {if (isRelayoutTracingEnabled()) {Trace.instantForTrack(TRACE_TAG_APP, "requestLayoutTracing",mTracingStrings.classSimpleName);printStackStrace(mTracingStrings.requestLayoutStacktracePrefix);}if (mMeasureCache != null) mMeasureCache.clear();if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {// Only trigger request-during-layout logic if this is the view requesting it,// not the views in its parent hierarchyViewRootImpl viewRoot = getViewRootImpl();if (viewRoot != null && viewRoot.isInLayout()) {if (!viewRoot.requestLayoutDuringLayout(this)) {return;}}mAttachInfo.mViewRequestingLayout = this;}mPrivateFlags |= PFLAG_FORCE_LAYOUT;mPrivateFlags |= PFLAG_INVALIDATED;if (mParent != null && !mParent.isLayoutRequested()) {mParent.requestLayout();}if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {mAttachInfo.mViewRequestingLayout = null;}}

在这里插入图片描述

1.2 requestLayoutDuringLayout方法源码
 /*** Called by {@link android.view.View#requestLayout()} if the view hierarchy is currently* undergoing a layout pass. requestLayout() should not generally be called during layout,* unless the container hierarchy knows what it is doing (i.e., it is fine as long as* all children in that container hierarchy are measured and laid out at the end of the layout* pass for that container). If requestLayout() is called anyway, we handle it correctly* by registering all requesters during a frame as it proceeds. At the end of the frame,* we check all of those views to see if any still have pending layout requests, which* indicates that they were not correctly handled by their container hierarchy. If that is* the case, we clear all such flags in the tree, to remove the buggy flag state that leads* to blank containers, and force a second request/measure/layout pass in this frame. If* more requestLayout() calls are received during that second layout pass, we post those* requests to the next frame to avoid possible infinite loops.** <p>The return value from this method indicates whether the request should proceed* (if it is a request during the first layout pass) or should be skipped and posted to the* next frame (if it is a request during the second layout pass).</p>** @param view the view that requested the layout.** @return true if request should proceed, false otherwise.*/boolean requestLayoutDuringLayout(final View view) {if (view.mParent == null || view.mAttachInfo == null) {// Would not normally trigger another layout, so just let it pass through as usualreturn true;}if (!mLayoutRequesters.contains(view)) {mLayoutRequesters.add(view);}if (!mHandlingLayoutInLayoutRequest) {// Let the request proceed normally; it will be processed in a second layout pass// if necessaryreturn true;} else {// Don't let the request proceed during the second layout pass.// It will post to the next frame instead.return false;}}

注释翻译:
由{@link android.view. view# requestLayout()}调用,如果视图层次是当前的正在进行布局检查。requestLayout()通常 不应该在布局期间调用,
除非容器层次结构知道它在做什么(即,只要
该容器层次结构中的所有子节点都在布局的末尾进行测量和布局
传递该容器)。如果requestLayout()被调用,我们将正确地处理它
通过在帧进行时注册所有请求者。在画面的最后,
我们检查所有这些视图,看看是否还有待处理的布局请求
指示它们没有被其容器层次结构正确处理。如果是这样的话
在这种情况下,我们清除树中所有这样的旗帜,以移除导致的有bug的旗帜状态
空白容器,并强制在此框架中通过第二个请求/测量/布局。如果
在第二次布局过程中接收到更多的requestLayout()调用,我们发布它们
请求转到下一帧,以避免可能的无限循环。

此方法的返回值指示请求是否应该继续
(如果它是第一次布局传递期间的请求)或应该跳过并发布到
下一帧(如果它是第二个布局传递期间的请求)。

查看请求布局的视图。

如果请求应该继续,则返回true,否则返回false。

requestLayoutDuringLayout方法源码-图文分析

在这里插入图片描述

1.3 总结
  • 当视图层次结构当前处于布局时,不应该调用requestLayout方法
  • 会调用measure方法和layout方法

二、invalidate

2.1 invalidate方法源码
 /*** Invalidate the whole view. If the view is visible,* {@link #onDraw(android.graphics.Canvas)} will be called at some point in* the future.* <p>* This must be called from a UI thread. To call from a non-UI thread, call* {@link #postInvalidate()}.*/public void invalidate() {invalidate(true);}

在这里插入图片描述

2.2 invalidate(boolean invalidateCache)方法源码
/*** This is where the invalidate() work actually happens. A full invalidate()* causes the drawing cache to be invalidated, but this function can be* called with invalidateCache set to false to skip that invalidation step* for cases that do not need it (for example, a component that remains at* the same dimensions with the same content).** @param invalidateCache Whether the drawing cache for this view should be*            invalidated as well. This is usually true for a full*            invalidate, but may be set to false if the View's contents or*            dimensions have not changed.* @hide*/@UnsupportedAppUsagepublic void invalidate(boolean invalidateCache) {invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);}

在这里插入图片描述

2.3 invalidateInternal方法源码
void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,boolean fullInvalidate) {if (mGhostView != null) {mGhostView.invalidate(true);return;}if (skipInvalidate()) {return;}// Reset content capture cachesmPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;mContentCaptureSessionCached = false;if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)|| (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)|| (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED|| (fullInvalidate && isOpaque() != mLastIsOpaque)) {if (fullInvalidate) {mLastIsOpaque = isOpaque();mPrivateFlags &= ~PFLAG_DRAWN;}mPrivateFlags |= PFLAG_DIRTY;if (invalidateCache) {mPrivateFlags |= PFLAG_INVALIDATED;mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;}// Propagate the damage rectangle to the parent view.final AttachInfo ai = mAttachInfo;final ViewParent p = mParent;if (p != null && ai != null && l < r && t < b) {final Rect damage = ai.mTmpInvalRect;damage.set(l, t, r, b);p.invalidateChild(this, damage);}// Damage the entire projection receiver, if necessary.if (mBackground != null && mBackground.isProjected()) {final View receiver = getProjectionReceiver();if (receiver != null) {receiver.damageInParent();}}}}

在这里插入图片描述

在这里插入图片描述

2.4 isOpaque方法源码
 /*** Indicates whether this View is opaque. An opaque View guarantees that it will* draw all the pixels overlapping its bounds using a fully opaque color.** Subclasses of View should override this method whenever possible to indicate* whether an instance is opaque. Opaque Views are treated in a special way by* the View hierarchy, possibly allowing it to perform optimizations during* invalidate/draw passes.** @return True if this View is guaranteed to be fully opaque, false otherwise.*/@ViewDebug.ExportedProperty(category = "drawing")public boolean isOpaque() {return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&getFinalAlpha() >= 1.0f;}

指示此视图是否不透明。一个不透明的视图保证它会这样做
使用完全不透明的颜色绘制与边界重叠的所有像素。

View的子类应该尽可能地覆盖这个方法
实例是否不透明。以一种特殊的方式处理不透明视图
视图层次结构,可能允许它执行优化期间
失效/画传递。

@return True如果这个视图保证是完全不透明的,否则返回false。

2.5 总结
  • 必须在主线程调用invalidate方法
  • invalidate方法会调用onDraw方法绘制新的内容

三、postInvalidate

3.1 postInvalidate方法源码
/*** <p>Cause an invalidate to happen on a subsequent cycle through the event loop.* Use this to invalidate the View from a non-UI thread.</p>** <p>This method can be invoked from outside of the UI thread* only when this View is attached to a window.</p>** @see #invalidate()* @see #postInvalidateDelayed(long)*/public void postInvalidate() {postInvalidateDelayed(0);}

在这里插入图片描述

3.2 postInvalidateDelayed方法源码
/*** <p>Cause an invalidate of the specified area to happen on a subsequent cycle* through the event loop. Use this to invalidate the View from a non-UI thread.</p>** <p>This method can be invoked from outside of the UI thread* only when this View is attached to a window.</p>** @param left The left coordinate of the rectangle to invalidate.* @param top The top coordinate of the rectangle to invalidate.* @param right The right coordinate of the rectangle to invalidate.* @param bottom The bottom coordinate of the rectangle to invalidate.** @see #invalidate(int, int, int, int)* @see #invalidate(Rect)* @see #postInvalidateDelayed(long, int, int, int, int)*/public void postInvalidate(int left, int top, int right, int bottom) {postInvalidateDelayed(0, left, top, right, bottom);}
3.3 postInvalidateDelayed(long delayMilliseconds)方法源码
/*** <p>Cause an invalidate to happen on a subsequent cycle through the event* loop. Waits for the specified amount of time.</p>** <p>This method can be invoked from outside of the UI thread* only when this View is attached to a window.</p>** @param delayMilliseconds the duration in milliseconds to delay the*         invalidation by** @see #invalidate()* @see #postInvalidate()*/public void postInvalidateDelayed(long delayMilliseconds) {// We try only with the AttachInfo because there's no point in invalidating// if we are not attached to our windowfinal AttachInfo attachInfo = mAttachInfo;if (attachInfo != null) {attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);}}
3.4 postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom) 方法源码
/*** <p>Cause an invalidate of the specified area to happen on a subsequent cycle* through the event loop. Waits for the specified amount of time.</p>** <p>This method can be invoked from outside of the UI thread* only when this View is attached to a window.</p>** @param delayMilliseconds the duration in milliseconds to delay the*         invalidation by* @param left The left coordinate of the rectangle to invalidate.* @param top The top coordinate of the rectangle to invalidate.* @param right The right coordinate of the rectangle to invalidate.* @param bottom The bottom coordinate of the rectangle to invalidate.** @see #invalidate(int, int, int, int)* @see #invalidate(Rect)* @see #postInvalidate(int, int, int, int)*/public void postInvalidateDelayed(long delayMilliseconds, int left, int top,int right, int bottom) {// We try only with the AttachInfo because there's no point in invalidating// if we are not attached to our windowfinal AttachInfo attachInfo = mAttachInfo;if (attachInfo != null) {final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();info.target = this;info.left = left;info.top = top;info.right = right;info.bottom = bottom;attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);}}

在这里插入图片描述

dispatchInvalidateDelayed方法
在这里插入图片描述

handleMessageImpl方法接收MSG_INVALIDATE消息
在这里插入图片描述

3.5 总结
  • 可以在非UI线程或UI线程中调用postInvalidate
  • 当调用postInvalidate()方法时,会调用dispatchInvalidateDelayed通过Handler将重绘任务添加到主线程的消息队列中。在UI线程的消息循环中,当处理到该消息时,会触发invalidate()方法来进行实际的重绘操作。

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

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

相关文章

C++ :友元类

友元类的概念和使用 (1)将类A声明为B中的friend class后&#xff0c;则A中所有成员函数都成为类B的友元函数了 (2)代码实战&#xff1a;友元类的定义和使用友元类是单向的 (3)友元类是单向的&#xff0c;代码实战验证 互为友元类 (1)2个类可以互为友元类&#xff0c;代码实战…

【LeetCode】二叉树的最大深度

目录 一、题目二、解法完整代码 一、题目 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3 示例 2&#x…

Leetcode2160. 拆分数位后四位数字的最小和:

问题描述&#xff1a; 给你一个四位 正 整数 num 。请你使用 num 中的 数位 &#xff0c;将 num 拆成两个新的整数 new1 和 new2 。new1 和 new2 中可以有 前导 0 &#xff0c;且 num 中 所有 数位都必须使用。 比方说&#xff0c;给你 num 2932 &#xff0c;你拥有的数位包括…

怎么剪辑音频文件?4款适合新的音频剪辑软件

是谁还不会音频剪辑&#xff1f;无论是个人音乐爱好者&#xff0c;还是专业音频工作者&#xff0c;我们都希望能找到一款操作简便、功能强大且稳定可靠的音频剪辑工具。今天&#xff0c;我就要为大家带来四款热门音频剪辑软件的体验感分享。 一、福昕音频剪辑 福昕音频剪辑是…

YOLO 模型基础入门及官方示例演示

文章目录 Github官网简介模式数据集Python 环境Conda 环境Docker 环境部署 CPU 版本官方 CLI 示例官方 Python 示例 任务目标检测姿势估计图像分类 Ultralytics HUB视频流示例 Github https://github.com/ultralytics/ultralytics 官网 https://docs.ultralytics.com/zhhttp…

【IEEE出版】第四届能源工程与电力系统国际学术会议(EEPS 2024)

第四届能源工程与电力系统国际学术会议&#xff08;EEPS 2024&#xff09; 2024 4th International Conference on Energy Engineering and Power Systems 重要信息 大会官网&#xff1a;www.iceeps.com 大会时间&#xff1a;2024年8月9-11日 大会…

2024年7月萤火虫航天为NASA发射8颗立方体卫星

作为美国宇航局立方体卫星发射计划的一部分&#xff0c;萤火虫航空航天公司于7月3日在该公司的阿尔法火箭上发射了八颗小型卫星。这枚名为“夏日噪音”的火箭于太平洋夏令时&#xff08;PDT&#xff09;晚上9点04分从加利福尼亚州范登堡空军基地的2号航天发射场成功升空。 立方…

解读vue3源码-响应式篇2

提示&#xff1a;看到我 请让我滚去学习 文章目录 vue3源码剖析reactivereactive使用proxy代理一个对象1.首先我们会走isObject(target)判断&#xff0c;我们reactive全家桶仅对对象类型有效&#xff08;对象、数组和 Map、Set 这样的集合类型&#xff09;&#xff0c;而对 str…

【数学建模】多波束测线问题(持续更新)

多波束测线问题 问题 1建立模型覆盖宽度海水深度重叠长度重叠率 问题二问题三问题四 问题 1 与测线方向垂直的平面和海底坡面的交线构成一条与水平面夹角为 α \alpha α的斜线&#xff08;如下图&#xff09;&#xff0c;称 α \alpha α为坡度。请建立多波束测深的覆盖宽度及…

Python代码,强化学习,深度学习

python代码编写&#xff0c;Python算法设计&#xff0c;强化学习优化&#xff0c;改进模型&#xff0c;训练模型&#xff0c;测试模型&#xff0c;可视化绘制&#xff0c;代编运行结果&#xff0c;交互多模型改进&#xff0c;预测模型&#xff0c;算法修改&#xff0c;Python包…

11.斑马纹列表 为没有文本的链接设置样式

斑马纹列表 创建一个背景色交替的条纹列表。 使用 :nth-child(odd) 或 :nth-child(even) 伪类选择器,根据元素在一组兄弟元素中的位置,对匹配的元素应用不同的 background-color。 💡 提示:你可以用它对其他 HTML 元素应用不同的样式,如 <div>、<tr>、<p&g…

利用PyTorch进行模型量化

利用PyTorch进行模型量化 目录 利用PyTorch进行模型量化 一、模型量化概述 1.为什么需要模型量化&#xff1f; 2.模型量化的挑战 二、使用PyTorch进行模型量化 1.PyTorch的量化优势 2.准备工作 3.选择要量化的模型 4.量化前的准备工作 三、PyTorch的量化工具包 1.介…

openGauss学习笔记-312 openGauss 数据迁移-MySQL迁移-迁移MySQL数据库至openGauss-概述

文章目录 openGauss学习笔记-312 openGauss 数据迁移-MySQL迁移-迁移MySQL数据库至openGauss-概述312.1 工具部署架构图 openGauss学习笔记-312 openGauss 数据迁移-MySQL迁移-迁移MySQL数据库至openGauss-概述 312.1 工具部署架构图 当前openGauss支持对MySQL迁移服务&#x…

【多任务YOLO】 A-YOLOM: You Only Look at Once for Real-Time and Generic Multi-Task

You Only Look at Once for Real-Time and Generic Multi-Task 论文链接&#xff1a;http://arxiv.org/abs/2310.01641 代码链接&#xff1a;https://github.com/JiayuanWang-JW/YOLOv8-multi-task 一、摘要 高精度、轻量级和实时响应性是实现自动驾驶的三个基本要求。本研究…

多光谱的空间特征和光谱特征Statistics of Real-World Hyperspectral Images

文章目录 Statistics of Real-World Hyperspectral Images1.数据集2.spatial-spectral representation3.Separable Basis Components4.进一步分析5.复现一下5.1.patch的特征和方差和论文近似&#xff0c;5.2 spatial的basis和 spectral的basis 6.coef model7.join model Statis…

多视角数据的不确定性估计:全局观的力量

论文标题&#xff1a;Uncertainty Estimation for Multi-view Data: The Power of Seeing the Whole Picture 中文译名&#xff1a;多视角数据的不确定性估计:全局观的力量 原文地址&#xff1a;Uncertainty Estimation for Multi-view Data: The Power of Seeing the Whole …

python用selenium网页模拟时xpath无法定位元素解决方法2

有时我们在使用python selenium xpath时&#xff0c;无法定位元素&#xff0c;红字显示no such element。上一篇文章写了1种情况&#xff0c;是包含iframe的&#xff0c;详见https://blog.csdn.net/Sixth5/article/details/140342929。 本篇写第2种情况&#xff0c;就是xpath定…

类和对象:赋值函数

1.运算符重载 • 当运算符被⽤于类类型的对象时&#xff0c;C语⾔允许我们通过运算符重载的形式指定新的含义。C规定类类型对象使⽤运算符时&#xff0c;必须转换成调⽤对应运算符重载&#xff0c;若没有对应的运算符重载&#xff0c;则会编译报错&#xff1b;&#xff08;运算…

数据旋律与算法和谐:LLMs的微调交响

论文&#xff1a;https://arxiv.org/pdf/2310.05492代码&#xff1a;暂未开源机构&#xff1a;阿里巴巴领域&#xff1a;模型微调发表&#xff1a;ACL 2024 这篇论文《How Abilities in Large Language Models are Affected by Supervised Fine-tuning Data Composition》深入…

【BUG】已解决:raise KeyError(key) from err KeyError: (‘name‘, ‘age‘)

已解决&#xff1a;raise KeyError(key) from err KeyError: (‘name‘, ‘age‘) 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xf…