Android invalidate()源码分析
发布日期:2021-10-04 02:53:49 浏览次数:7 分类:技术文章

本文共 2593 字,大约阅读时间需要 8 分钟。

Android View源码中的invalidate()在开发中经常使用,尤其是自定义控件,还有View的动画基本都是直接调用该方法引起重绘。该方法会使View全部或者部分重绘,具体取决于传入参数、View透明度、View是否在动画以及View是否开启硬件加速绘制等。其主要调用流程如下:

invalidate()分析

简单总结如下:

1.直接调用invalidate()函数,其内部实际是调用invalidate(true)。这里的参数代表是否是完全重绘。完全重绘与否其实就是是否使用绘制缓存去绘制的问题。

2.在invalidate(true)函数中:

(1)首先去确认该View是否需要跳过绘制,这里其实就是一个判断条件。跳过绘制条件:View不是可见的 && 存在动画对象 && 父视图不是ViewGroup或者不是过渡态。只有满足以上条件才可以跳过绘制直接返回。

(2)接着要确认在如下条件才可以重绘:正在动画或者View大小不是0 || 需要完整绘制绘制并且绘制缓存可用 || 未重绘过 || 透明度和上次比较有了变化。满足以上条件中的一个就可以执行重绘。

(3)对是否完全重绘设置,即该函数传入的参数。其实就是设置绘制缓存不可用的标识到mPrivateFlags。在绘制的时候会根据该标识决定是否使用绘制缓存。当然如果是绘制缓存可用的时候需要在绘制的时候先绘制View到Bitmap缓存,如果已经存在该缓存就直接将缓存绘制到canvas。如果是完整重绘就跳过绘制缓存和使用绘制缓存的步骤直接去重绘View到canvas。

(4)接下来就要去ViewParent中去执行。在执行之前分了两种情况去处理,分别是硬件加速可用和不可用的情况。在硬件加速可用的情况传入invalidateChild()的dirty参数为null,代表需要重绘这个View层级。而使用软件绘制时传入的是根据View大小构造的dirty矩阵。需要指出这里的ViewParent一般是值ViewGroup。这里只分析软件绘制。

3.在ViewGroup中去执行invalidateChild():

(1)初始化变量:是否在动画中、View变化矩阵、是否不透明、记录子View相对于父ViewGroup的相对坐标。不透明判断主要是根据:需要重绘child的不透明度 && 无动画 && child变化矩阵无变化。记录坐标主要是为了将带绘制的dirty矩阵与ViewGroup可显示矩阵做相交或者相并处理。

(2)处理child变化矩形与ViewGroup变换对象对dirty矩阵的影响。首先对ViewGroup设置的静态变换对象做处理,获取设置的变换对象然后获取其变换矩阵,将child的原矩阵和获取的矩阵做合并处理,最后将处理之后的矩阵应用到dirty矩阵,同时也将child的变化矩阵应用到dirty矩阵。

(3)do-while循环设置ViewGroup属性同时处理该child的dirty矩阵与ViewGroup可显示矩阵的关系:

  • 如果正在动画设置分ViewParent类型设置动画标识。

  • 设置ViewGroup的DIRTY标识待重绘。

  • 调用invalidateChildInParent()处理该child的dirty矩阵与ViewGroup可显示矩阵的关系,同时返回该ViewGroup的ViewParent以便下次循环接着调用。

  • 经过上面步骤的dirty矩阵此时已经与ViewGroup可显示矩阵做处理了。如果是ViewGroup将其变化的变换矩阵应用与child的dirty矩阵。

4.在以上循环中调用的invalidateChildInParent()由两种实现。分别是在ViewGroup中实现和ViewRootImpl实现。该循环结束前的最后一次调用一定是ViewRootImpl的实现。

(1)对ViewGroup中的实现做介绍。

  • 首先判断条件:存在动画 || 动画缓存可用。只有该条件满足才会执行否则直接返回null。

  • 接着判断条件:如果是已完成动画或者是没有动画时。首先将dirty位置坐标偏移至相对于父View可视区域原点的坐标。接着处理如果不需要剪裁child直接将dirty与ViewGroup整体大小求并集。之所以需要ViewGroup整体大小求并集是因为涉及到子View动画,ViewGroup需要重绘自身完整区域。如果需要剪裁child则将dirty矩阵与ViewGroup整体大小求交集,如果不存在交集则直接置空dirty矩阵。接着更新location为该ViewGroup相对于其ViewParent的相对坐标。最后返回其ViewParent。

  • 如果是以上判断的对立面,即正在动画中:更新location为该ViewGroup相对于其ViewParent的相对坐标。如果需要剪裁child则直接设置dirty为该ViewGroup整体的大小。如果不需要直接dirty与整体大小求并集。最后返回其ViewParent。

可以看到以上两点的处理是VIew是否动画为主。如果在动画最后dirty处理完要么是ViewGroup整体大小要么比他大。如果不在动画则有可能小于ViewGroup整体大小。这也是子View动画会完全影响到其ViewGroup绘制的原因。

(2)对ViewRootImpl的实现介绍。

  • 首先检测该线程是否是UI线程,如果不是直接抛出异常。

  • 对dirty检查处理。如果是null,直接设置dirty为整个大小重绘。如果是空并且不在动画直接返回null。如果ViewRoot存在偏移mCurScrollY转化dirty位置到相对于ViewRoot可视区域的坐标。

  • 将dirty添加到待重绘区域。获取上次重绘的矩阵localDirty与dirty求并集。处理窗口缩放然后将处理后的大小与localDirty求交集,如果没有交集置空localDirty。

  • 重绘任务。满足如下条件:performTraversal()未执行 && localDirty与窗口存在交集或者正在动画。调用任务scheduleTraversals();最后返回null。

所以最后一次do循环一定是调用ViewRootImpl中的该方法实现,最后执行绘制任务的。

至此,invalidate()源码介绍完毕。

转载地址:https://blog.csdn.net/leif_/article/details/50596085 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Android MediaCodec使用介绍
下一篇:Android View 绘制流程

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年03月05日 05时25分22秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

grouping函数 mysql_sql聚合函数有哪些 2019-04-21
python os.walk如何不遍历隐藏文件_python 获取文件下所有文件或目录os.walk()的实例... 2019-04-21
python 股票估值_【中金固收·固收+】隐藏价值的角落:限售股AAP估值及Python实现方法(上)... 2019-04-21
java文档生成_Java文档自动生成 2019-04-21
java 共享目录_java 操作windows 共享目录方法介绍 2019-04-21
java 监控 宕机_JAVA监测tomcat是否宕机,控制重启 2019-04-21
catch that cow java_POJ3278——Catch That Cow 2019-04-21
java integer 不变模式_Java代码的变与不变 2019-04-21
java guava 使用_Java8-Guava实战示例 2019-04-21
python barrier option pricing_《Python金融数据分析》书内代码实战与讲解(二)金融衍生物定价... 2019-04-21
java自带工具_深入了解Java JDK自带工具,包括javac、jar、jstack等,实用~ 2019-04-21
gnome mysql client_解决MySQLWorkbenchgnome-keyring-daemon错误的方法分享 2019-04-21
java线程占用CPU_在windows下揪出java程序占用cpu很高的线程并完美解决 2019-04-21
java多态替换switch_使多态性无法解决那些switch / case语句的麻烦 2019-04-21
java httpclient 进度条_如何使用Apache HttpClient 4获取文件上传的进度条? 2019-04-21
下列不属于java语言特点的是_下列选项中,不属于Java语言特点的一项是( )。... 2019-04-21
java中小数的乘法_javascript的小数点乘法除法实例 2019-04-21
kappa一致性检验教程_SPSS在线_SPSSAU_Kappa一致性检验 2019-04-21
linux shell mysql备份_linux shell 备份mysql 数据库 2019-04-21
Java双向链表时间复杂度_链表是什么?有多少种链表?时间复杂度是? 2019-04-21