Android面试:Invalidate、RequestLayout
Invalidate/RequestLayout区别
先放上结论
- requestLayout会直接递归调用父窗口的requestLayout,直到ViewRootImpl,然后触发peformTraversals,由于mLayoutRequested为true,会导致onMeasure和onLayout被调用。不一定会触发OnDraw
- requestLayout触发onDraw可能是因为在在layout过程中发现l,t,r,b和以前不一样,那就会触发一次invalidate,所以触发了onDraw,也可能是因为别的原因导致mDirty非空(比如在跑动画)
- view的invalidate不会导致ViewRootImpl的invalidate被调用,而是递归调用父view的invalidateChildInParent,直到ViewRootImpl的invalidateChildInParent,然后触发peformTraversals,会导致当前view被重绘,由于mLayoutRequested为false,不会导致onMeasure和onLayout被调用,而OnDraw会被调用
面试:硬件加速相关_沙漠一只雕得儿得儿的博客-CSDN博客
在硬件加速关闭时,绘制内容会被 CPU 转换成实际的像素,然后直接渲染到屏幕。具体来说,这个「实际的像素」,它是由 Bitmap 来承载的。在界面中的某个 View 由于内容发生改变而调用 invalidate() 方法时,如果没有开启硬件加速,那么为了正确计算 Bitmap 的像素,这个 View 的父 View、父 View 的父 View 乃至一直向上直到最顶级 View,以及所有和它相交的兄弟 View,都需要被调用 invalidate()来重绘。一个 View 的改变使得大半个界面甚至整个界面都重绘一遍,这个工作量是非常大的。
而在硬件加速开启时,前面说过,绘制的内容会被转换成 GPU 的操作保存下来(承载的形式称为 display list,对应的类也叫做 DisplayList),再转交给 GPU。由于所有的绘制内容都没有变成最终的像素,所以它们之间是相互独立的,那么在界面内容发生改变的时候,只要把发生了改变的 View 调用 invalidate() 方法以更新它所对应的 GPU 操作就好,至于它的父 View 和兄弟 View,只需要保持原样。那么这个工作量就很小了。
正是由于上面的原因,硬件加速不仅是由于 GPU 的引入而提高了绘制效率,还由于绘制机制的改变,而极大地提高了界面内容改变时的刷新效率。
结合requestLayout和invalidate与View三大流程关系,有如下图:
1、当视图的内容,可见性发生变化,会调用invalidate,调用后只会触发Draw 过程。
2、requestLayout