【Android每日一问】invalidate和requestLayout的原理以及区别

1,905 阅读1分钟

invalidate原理

  • view的invalidate会逐层找parent一直找到DecorView,DecorView是顶层view,它有个虚拟父view为ViewRootImpl。ViewRootImpl不是一个view或者viewGroup,它的成员mView就是DecorView,所有的操作从ViewRootImpl自上而下开始分发。

  • view的invalidate不会导致ViewRootImpl的invalidate被调用,而是递归调用父view的invalidateChildInParent,直到ViewRootImpl的invalidateChildInParent,然后触发peformTraversals,会导致当前view被重绘,由于mLayoutRequested为false,不会导致onMeasure和onLayout被调用,而OnDraw会被调用。

  • 一个view的invalidate会导致本身PFLAG_INVALIDATED置为1,导致本身以及父族viewgroup的PFLAG_DRAWING_CACHE_VALID置为0。

所以,invalidate如果是个view,那就只有自己本身会draw,如果是ViewGroup就是对子view进行重绘。

requestLayout原理

  • requestLayout会直接递归调用父的requestLayout,直到ViewRootImpl,然后触发peformTraversals,由于mLayoutRequested为true,会导致onMeasure和onLayout被调用。不一定会触发OnDraw。

  • requestLayout触发onDraw可能是因为在在layout过程中发现left,top,right,bottom和以前不一样,那就会触发一次invalidate,所以触发了onDraw。

  • requestLayout会导致自己以及父view的PFLAG_FORCE_LAYOUT和PFLAG_INVALIDATED标志被设置。

所以,view的requestLayout必然会导致该view和viewparent的重新measure,但不一定会导致子view的measure。

一般来说,只要刷新的时候就调用invalidate,需要重新measure就调用requestLayout,后面再跟个invalidate(为了保证重绘)。