1. invalidate
invalidate:重新绘制的意思
2. invalidate()源码
// 这个其实就是 invalidate() 重绘
void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
boolean fullInvalidate) {
// 首先调用 skipInvalidate判断,当前 view 是否需要重新绘制
if (skipInvalidate()) {
return;
}
// 然后调用 ViewGroup的 invalidateChild
p.invalidateChild(this, damage);
}
}
// 判断 当前 view 是否需要重绘,判断逻辑是:如果当前view不可见并且没有动画,就不用重绘
private boolean skipInvalidate() {
return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
(!(mParent instanceof ViewGroup) ||
!((ViewGroup) mParent).isViewTransitioning(this));
}
ViewGroup的 invalidateChild()方法:
public final void invalidateChild(View child, final Rect dirty) {
ViewParent parent = this;
// 这里是一个 do...while循环,
do {
View view = null;
if (parent instanceof View) {
// 这里不断的获取当前 view 的 父view布局 ,然后最终就会 获取到最外层的 ViewGroup
view = (View) parent;
}
// 然后调用 ViewGroup的 invalidateChildInParent ,作用是计算要绘制的矩形区域
// 当循环到最外层后,就调用 ViewParent.invalidateChildInParent
parent = parent.invalidateChildInParent(location, dirty);
}
} while (parent != null);
}
}
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
checkThread();
scheduleTraversals();
}
分析上边源码:
1>:在 invalidate 方法中:首先调用 skipInvalidate,作用是 判断当前 view 是否需要重新绘制,判断逻辑是:
如果当前 view 不可见并且没有动画,就不用重绘;
如果需要重绘:调用 ViewGroup.invalidateChild;
2>:在 ViewGroup的 invalidateChild 中:
有一个 do...while循环,在do中不断的获取当前view的父view (只是当前的view的父布局,并不是最外层ViewGroup),然后调用 该view的父布局的invalidateChildInParent,一直调用到最外层的 ViewGroup(这个才是最外层的ViewGroup)的 invalidateChildInParent;
然后中间会经过一系列调用,调用到 performTraversals(),然后调用 performDraw;
当调用到最外层后,就开始从最外层向最里层绘制, 从最外层开始调用view的 draw绘制,然后一直调用到最里层 view 的 draw 进行绘制;
这个就是 invalidate() 绘制流程
3. 总结
1>:invalidate绘制流程就是:从当前view 不断的获取它的 父布局ViewGroup,一直获取到最外层的ViewGroup,然后从最外层的 ViewGroup 开始调用 draw绘制,一直绘制到最里层当前 view;
2>:invalidate只是调用performDraw,没有调用 performMeasure、performLayout,如果需要执行完整的绘制流程,可以调用 requestLayout
3>:流程图如下:

4. invalidate调用时机
代码中只要调用 setText()、setVisibility()、setEnable()、setFocused()等方法,里边都会调用 invalidate()方法,表示 强制让view 重绘;
只要一调用 invalidate,不断获取当前view 的 父布局,然后调用父布局的 invalidateChildInParent,一直调用到最外层的 ViewGroup的 invalidateChildInParent,然后再从最外层开始一直向最里层的view调用 draw绘制,每调用一次invalidate方法都会牵连整个layout布局,如果多次调用,就会影响页面卡顿;
网友评论