requestLayout调用onDraw之谜

Android面试:Invalidate、RequestLayout Invalidate/RequestLayout 使用场合 结合requestLayout和invalidate与View三大流程关系,有如下图: 总结一下: 1、invalidate调用后只会触发Draw 过程。 2、requestLayout 会触发Measure、Layout过程,如果尺寸发生改变,则会调用invalidate。 3、当涉及View的尺寸、位置变化时使用requestLayout。 4、当仅仅需要重绘时调用invalidate。 5、如果不确定requestLayout 是 阅读详情

在上篇文章曾经说过,requestLayout如果没有改变l,t,r,b,那就不会触发onDraw,但是我今天写了个demo,发现居然触发了onDraw,这是怎么回事?
代码很简单,工程为RequestLayoutDemo

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main"
    tools:context="com.fish.a1.MainActivity">

    <com.fish.a1.ATextView
        android:id="@+id/b0"
        android:text="Hello World!"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:layout_toRightOf="@id/b0"
        android:id="@+id/b1"
        android:text="Hello World!"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>
        findViewById(R.id.b1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                View v1=findViewById(R.id.b0);
                v1.requestLayout();

            }
        });

原理分析

Button按下首先是出现按下效果,然后触发click事件,click事件是post出去的,不是立刻发生的。所以Button按下,首先出现press效果,然后触发click事件,会导致2轮doTraversal。

第一轮doTraversal

Button按下会触发动画,导致ViewRootImpl#invalidate,调用堆栈如下

由下可知,mDirty会被设置为全屏,并且触发一次scheduleTraversals

//ViewRootImpl#invalidate
    void invalidate() {
        mDirty.set(0, 0, mWidth, mHeight);
        if (!mWillDrawSoon) {
            scheduleTraversals();
        }
    }

然后performTraversals被触发,内调用performDraw,里面调用draw,里面先把mDirty清空,然后调mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);里面调updateRootDisplayList,里面调updateViewTreeDisplayList,简单的说就是performDraw里面调用了ThreadedRenderer#updateViewTreeDisplayList(View v)
,此时v是DecorView,看下面的代码,此时DecorView的PFLAG_INVALIDATED么有被设置,所以根本不会被重绘(参考上篇文章)。

//android.view.ThreadedRenderer#updateViewTreeDisplayList
    private void updateViewTreeDisplayList(View view) {
        view.mPrivateFlags |= View.PFLAG_DRAWN;
        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
                == View.PFLAG_INVALIDATED;
        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
        view.updateDisplayListIfDirty();
        view.mRecreateDisplayList = false;
    }

第二轮doTraversal

此时触发click事件,调用v1.requestLayout();,会把DecorView的PFLAG_INVALIDATED标志位给设置起来,并且触发performTraversals。
此时Button动画还在刷新,所以又调用ViewRootImpl#invalidate把mDirty给设置成全屏,并且触发performTraversals。
动画要的performTraversals和刷新要的performTraversals会合并成一个doTraversal。内调用performDraw,里面调用draw,里面先把mDirty清空,然后调mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);里面调updateRootDisplayList,里面调updateViewTreeDisplayList,简单的说就是performDraw里面调用了ThreadedRenderer#updateViewTreeDisplayList(View v)
,此时v是DecorView,注意此时DecorView的PFLAG_INVALIDATED标志位已经被设置了,所以会重绘,所以ATextView的ondraw会被调用。

其他

如果我把Button改为TextView,那么按下TextView就不会触发ATextView的ondraw了,因为没有按下动画。

总结

requestLayout如果没有改变l,t,r,b,那就不会触发onDraw;但是如果这次刷新是在动画里,mDirty非空,就会导致onDraw

requestlayout,onlayout,onDraw,invalidate区别与联系 invalidate流程图: 11764 void More ...invalidate(boolean invalidateCache) { 11765 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true); 11766 }void More ...invalida 阅读详情

相关推荐

requestLayout和invalidate区别

requestLayout: requestLayout会直接递归调用父窗口的requestLayout,直到ViewRootImpl,然后触发peformTraversals,由于mLayoutRequested为true,会导致onMeasure和onLayout被调用。不一定会触发OnDraw。requestLayout触发onDraw可能是因为在在layout过程中发现l,t,r,b和以...

汉堡怪兽 1万+

requestLayout、forceLayout、invalidate、postInvalidate总结

postInvalidate 在非UI线程调用 invalidate() Callinginvalidate()is done when you want to schedule a redraw of the view. It will result inonDrawbeing called eventually (soon, but not immediately). A...

Ulez_柚子的博客 464

【Android面试八股文】你来说一说你来说一说requestlayout(), onLayout(),onDraw(), drawchild()区别与联系

通过以上步骤,我们从调用开始,一步一步地跟踪到onLayout()和onDraw()方法的调用过程。触发了一系列的测量、布局和绘制操作,确保视图树的正确更新和显示。:通知系统视图的布局需要更新,会触发measure()和layout()。onLayout():在布局阶段被调用,用于放置视图和子视图的位置和大小。onDraw():在绘制阶段被调用,用于实际的绘制操作。:用于在自定义 ViewGroup 中绘制子视图,提供了对子视图绘制的精细控制。

字节卷动 545

Android View requestLayout 与 onDraw跟onMeasure的关系(一)

Android View requestLayout 与 onDraw跟onMeasure的关系(一)Android View requestLayout 与 onDraw跟onMeasure的关系一 requestLayout 简介 源码分析requestLayout如果一个View的大小、位置等View的形状发生变化后,我们可以调用这个函数请求重新布局,将变化后的View更新到屏幕上。如果子Vi

Tauren的专栏 2207

麒麟V10系统下CoreDump文件自动归档与快速定位指南(附coredumpctl实战)

本文详细介绍了在麒麟V10操作系统下,如何利用systemd-coredump机制和coredumpctl工具实现CoreDump文件的自动化管理与高效调试。内容涵盖从系统架构解析、自动化配置策略,到使用coredumpctl进行快速查询、过滤与深度分析的实战指南,旨在帮助运维人员和开发者快速定位系统崩溃的根本原因,提升问题排查效率。

gg901的博客 222

PTA 7-8 暴力小学(二年级篇)-求出4个数字 (10分)java

PTA 7-8 暴力小学(二年级篇)-求出4个数字 (10分)java 小博是新城小学二年级学生,这孩子人很老实,数学、语文成绩都是中等。不过一旦坐在电脑前,写起代码来,则有些霸气侧漏,尤其擅长各种暴力方法。本题就是数学莫老师的题目之一,请你和小博一起暴力求解吧。 输入格式: 第一行给出这个和N(图中例子的和N为2000)。 输出格式: 第一行输出所有解的数目K,随后K行按照DCBA 4位数字从...

qryzhfj的博客 2190

绘图/更新UI,重绘requestLayout() invalidate()和postInvalidate()

1.Android中实现view的更新? 2.重新绘制某个View,或绘制整个layout?> View.add(); View.remove(); View.update() 动态添加和删除View,然后会走onMeasure(),onLayout(),onDraw()哪些方法? > 适配器adapter的notifyDataSetChanged和notifyDataSetInv...

ShareUs的专栏 1620

学好超几何分布的核心公式,破解双色球!

彩票本质是概率游戏,不存在"必中公式"科学投注的核心是风险收益比管理长期投注的期望值始终为负(理论回报率约47%-63%)数学维度:运用概率工具优化策略经济维度:控制投注成本在可承受范围人文维度:将彩票视为社会公益的参与方式通过本文构建的数学模型,彩民可以在概率框架内实现更理性的投注决策。但最终能否收获幸运,仍取决于那个永恒的未知数——概率女神的眷顾。一、超几何分布的核心公式。

weixin_44904675的博客 1万+

RequestLayout() , Invalidate() , layout()之间的区别

在自定义控件的过程会遇到以上方法,三个方法的区别如下: 1. requeLayout() : 控件会重新执行 onMesure() onLayout() ,比如 ScrollView中有LinearLaout ,LinearLayout里面有纵向排列的ImageView和TextView,那么假如ImageView的长宽发生了变化,而要立即在手机上显示这个变化的话,就可调用 imageView.

Code Issuer的博客 1万+

EMC辐射发射测试:垂直与水平极化测试原理与实战指南

电磁兼容(EMC)测试是确保电子设备在复杂电磁环境中稳定运行的关键环节,其核心在于评估设备产生的电磁干扰(EMI)强度。辐射发射测试作为EMC测试的重要组成部分,通过测量设备向空间辐射的电磁噪声,判断其是否符合国际标准限值。测试原理基于电磁波的极化特性,即电场矢量的振动方向,主要分为垂直极化和水平极化。理解极化特性对于精准定位辐射源、高效进行EMC整改具有重要技术价值。在工程实践中,垂直极化噪声通常源于线缆辐射等垂直结构,而水平极化噪声多来自PCB走线等水平结构。通过分别测量两种极化方向的辐射最大值,可以全

weixin_32770423的博客 359

计算机网络之NAT的解释与实验配置

NAT 静态NAT 动态NAT easy_ip NAT服务器映射

爱学习的JackYang的博客 1918

你用对了吗Requestlayout,onlayout,onDraw,DrawChild

是视图布局(Layout)和绘制(Draw)流程中的关键方法。它们的作用和调用顺序密切相关,但职责不同。在 Android 的视图系统中,

时小雨的专栏 1066

避坑指南:用逐飞开源库驱动MT9V03X摄像头时容易忽略的3个细节(附TFT显示优化技巧)

本文详细解析了在智能汽车竞赛中使用MT9V03X摄像头(总钻风)时常见的硬件连接、图像采集和TFT显示优化问题。重点介绍了逐飞开源库中容易被忽略的三个关键细节,包括电源管理、看门狗设置和中断优先级配置,并提供了针对IPS200和TFT180显示屏的优化技巧,帮助参赛队伍提升图像处理效率和显示质量。

study的专栏 746

View的绘制流程二 requestLayout

若要ViewGroup onDraw()执行,只需要setWillNotDraw(false)、设置背景、设置前景、设置焦点高亮,4个选项其中一项满足即可。当然如果不想在 继承ViewGroup的自定义View onDraw里绘制,也可以重写ViewGroup dispatchDraw()方法,在该方法里绘制 自定义View 内容。

qq_42426725的博客 1123

基于Xilinx K7-410T的高速DAC之AD9129开发笔记(一)

引言:从本文开始,我们介绍下项目中设计的并行LVDS高速DAC接口设计,包括DAC与FPGA硬件接口设计、软件设计等。项目设计高速DAC采用了ADI公司的AD9129,该芯片最大更新速率5.7Gsps,该芯片在宽带通信应用、LTE、雷达信号产生、干扰机等领域有广泛应用。

FPGA_Designer 2535

Ubuntu零基础教学-如何把Ubuntu20.04界面从英文修改为中文?| 超级详细,建议收藏

带你如何把Ubuntu20.04界面从英文修改为中文?| 超级详细,建议收藏

**My Coding Family** 5340

Requestlayout,onlayout,onDraw,DrawChild区别与联系

requestLayout()方法 :会导致调用measure()过程 和 layout()过程 。 说明:只是对View树重新布局layout过程包括measure()和layout()过程,不会调用draw()过程,但不会重新绘制 任何视图包括该调用者本身。 onLayout()方法(如果该View是ViewGroup对象,需要实现该方法,对每个子视图进行布局) 调用onDraw()方法绘

qq_34378183的博客 2479

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

requestLayout()与onLayout();onDraw()与drawChild()的区别和联系

requestLayout()与onLayout()

QG 490

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

invalidate、requestlayout是否会调用ondraw?

凡是无绝对,在继承至ViewGroup的自定义控件中,invalidate是默认不重新绘制子view的。有以下两种方法来触发重新绘制的过程:方法一:在构造函数中调用setWillNotDraw(false);方法二:给ViewGroup设置背景。调用setBackground。通过源码分析,两个方法都是一个逻辑:需要将ViewGroup的dirtyOpaque设置为false.这样其父类的draw...

2746

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

invalidate() requestLayout()区别,什么场景调用?

Invalidate调用onDraw方法 requestLayout调用onMeasure和onLayout,不一定调用onDraw requestLayout : 当当前布局的宽高发生改变的时候, 此时需要重新调用父view的onMeaure和onLayout, 来给子view重新排版布局 invalidate : 让页面刷新, 重新调用onDraw方法, postInvalidate : 在子...

皮卡丘的博客 432

android invalidate()与requestLayout()区别

invalidate与requestLayout的区别invalidate()与requestLayout()是view中的方法invalidate()requestLayout() invalidate()与requestLayout()是view中的方法 代码添加一个自定义view,view显示在屏幕上的工作流程: new CustomView->ViewGroup.addView(Cu...

u013552367的博客 1211

View之requestLayout使用

这篇文章对于一些原理写的比较详细view原理问题接下来我做一下总结,然后给出一些使情景下的使用。 view的绘制过程: 1、measure:测量view的宽高 2、layout:确定view再父控件中的放置位置 3、draw:负责将view绘制再屏幕上 关键生命周期: --> 构造View() --> onFinishInflate() --> onAttachedTo...

chengzuidongfeng的博客 1027

android中invalidate和requestLayout区别

View有两个很重要的方法:invalidate和requestLayout,常用于View重绘和更新。 1. requestLayout To initiate a layout, call requestLayout(). This method is typically called by a view on itself when it believes that it can no longer fit within its current bounds. ——摘自View源码 从上面这句话看出,

stonezry的专栏 1398

invalidate(),postInvalidate()和requestLayout()区别

这三个方法都是用于触发视图更新的,但它们的应用场景和触发的“更新级别”完全不同。

hxltech的专栏 969
上一篇: 10fitsSystemWindows对CoordinatorLayout的影响
下一篇: 8CollapsingToolbarLayout源码分析
litefish
博客等级 码龄12年 116粉丝 199原创
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值