分析点击按钮导致背景切换,其中invalidate流程分析
![](https://img-my.csdn.net/uploads/201212/23/1356223534_4639.gif)
一 先看下之前从打印LOG的方法感性的认识Invalidate流程
View invalidateDrawable(Drawable drawable)
View invalidate , l = 0 , t = 0 , r = 90 , b = 90
LinearLayout invalidateChildInParent Rect Left = 0, right = 90, top = 0, bottom = 90
RelativeLayout invalidateChildInParent Rect Left = 55, right = 145, top = 55, bottom = 145
之前是先感性认识,从打出的log查看invalidate调用流程,这些log都是Android提供的回调方法中输出LOG,如果invalidate流程中有私有方法,就肯定跟踪不到。
所以现在从源码的角度来分析此流程。
二 大致从源码的调用角度分析Invalidate流程,了解些细节
Android 使用dmeo和源码分析invalidate流程
三 Invalidate流程引发的疑惑
四 当前使用方法调用堆栈的方法分析invalidate流程
分析源码要有一个开始的地方,从之前输出LOG来看第一个执行invalidateDrawable,执行的整体流程中,肯定是先触发onTouchEvent,
这里不分析整个流程仅仅先通过方法调用堆栈跟踪下Invalidate流程
先后顺序 | 类名 | 最终执行方法 |
---|---|---|
1 | InvalidateView | View.invalidateDrawable(Drawable drawable) |
2 | InvalidateView | View.invalidate(int l, int t, int r, int b) |
3 | InvalidateLinearLayout | ViewGroup.invalidateChild(View child, final Rect dirty) |
4 | InvalidateLinearLayout | ViewGroup.invalidateChildInParent(int[] location, Rect r) |
5 | InvalidateRelativeLayout | ViewGroup.invalidateChildInParent(int[] location, Rect r) |
6 | ViewRootImpl | ViewRootImpl.invalidateChildInParent(final int[] location, final Rect dirty) |
7 | 同上 | ViewRootImpl.invalidateChild(View child, Rect dirty) |
8 | 同上 | ViewRootImpl.scheduleTraversals() |
9 | 同上 | ViewRootImpl.performTraversals() |
10 | onMeasure, onLayout,onDraw |
其中向上传递最重要的就是4,5,6三个步骤,其调用层级关系在ViewGroup.invalidateChild方法中处理
public final void invalidateChild(View child, final Rect dirty) {
// parent初始值是当前ViewGroup自身
ViewParent parent = this;
......
do {
View view = null;
if (parent instanceof View) {
view = (View) parent;
}
......
// 返回当前ViewGroup的父视图的调用
parent = parent.invalidateChildInParent(location, dirty);
......
} while (parent != null); // 循环
}