天天记录 - Android 使用dmeo和源码分析invalidate流程

来源:互联网 发布:php 10进制转36进制 编辑:程序博客网 时间:2024/04/30 16:42





点击和抬起Button后,总共执行6次以下流程,LOG如下

Button  invalidateDrawable(Drawable drawable)Button  invalidate , l = 0 , t = 0 , r = 480 , b = 72LinearLayout   invalidateChildInParent




    从源码查看下Invalidate的执行流程。


    从打印出的LOG来看,点击后会先触发Button的invalidate函数,然后调用父控件LinearLayout的invalidate。


    1. 从LOG来看会首先调用Button.invalidateDrawable函数,未分析何处调用invalidateDrawable,这里不关心谁最初调用的,仅从invalidateDrawable函数开始分析源码。但是Button中没有invalidateDrawable函数其父类TextView.invalidateDrawable函数源码:


TextView.invalidateDrawable

    @Override    public void invalidateDrawable(Drawable drawable) {        // 验证是否显示Drawable,此方法可以覆写        if (verifyDrawable(drawable)) {            // 从drawable获取绘制区域            final Rect dirty = drawable.getBounds();                        ......            // 调用View.invalidate重绘指定区域            invalidate(dirty.left + scrollX, dirty.top + scrollY,                    dirty.right + scrollX, dirty.bottom + scrollY);        }    }


View.invalidate

    public void invalidate(int l, int t, int r, int b) {        // 如果不显示也不是动画,不会执行刷新        if (skipInvalidate()) {            return;        }        // 执行此分支,并设置mPrivateFlags三个属性        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;            mPrivateFlags |= PFLAG_INVALIDATED;            mPrivateFlags |= PFLAG_DIRTY;            final ViewParent p = mParent;            final AttachInfo ai = mAttachInfo;                        // 此分支不会被执行            //noinspection PointlessBooleanExpression,ConstantConditions            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {                if (p != null && ai != null && ai.mHardwareAccelerated) {                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy                    // with a null dirty rect, which tells the ViewAncestor to redraw everything                    p.invalidateChild(this, null);                    return;                }            }                        // 因为显示的坐标系是x轴从左向右递增 left < right            // y轴是从上向下递增 top < bottom             if (p != null && ai != null && l < r && t < b) {            // 处理滚动后的值                final int scrollX = mScrollX;                final int scrollY = mScrollY;                final Rect tmpr = ai.mTmpInvalRect;                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);                // 针对当前例子,Button调用的是LinearLayout.invalidateChild                p.invalidateChild(this, tmpr);            }        }    }

LinearLayout中没有invalidateChild函数实现,所以在父控件ViewGroup中查找ViewGroup.invalidateChild


ViewGroup.invalidateChild


    public final void invalidateChild(View child, final Rect dirty) {        ViewParent parent = this;        final AttachInfo attachInfo = mAttachInfo;        // 值非空,执行此分支        if (attachInfo != null) {            // If the child is drawing an animation, we want to copy this flag onto            // ourselves and the parent to make sure the invalidate request goes            // through            final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION)                    == PFLAG_DRAW_ANIMATION;            // Check whether the child that requests the invalidate is fully opaque            // Views being animated or transformed are not considered opaque because we may            // be invalidating their old position and need the parent to paint behind them.            Matrix childMatrix = child.getMatrix();            final boolean isOpaque = child.isOpaque() && !drawAnimation &&                    child.getAnimation() == null && childMatrix.isIdentity();            // Mark the child as dirty, using the appropriate flag            // Make sure we do not set both flags at the same time            int opaqueFlag = isOpaque ? PFLAG_DIRTY_OPAQUE : PFLAG_DIRTY;            // 不执行此分支            if (child.mLayerType != LAYER_TYPE_NONE) {                mPrivateFlags |= PFLAG_INVALIDATED;                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;                child.mLocalDirtyRect.union(dirty);            }            final int[] location = attachInfo.mInvalidateChildLocation;            location[CHILD_LEFT_INDEX] = child.mLeft;            location[CHILD_TOP_INDEX] = child.mTop;            // 不执行此分支            if (!childMatrix.isIdentity() ||                    (mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {                RectF boundingRect = attachInfo.mTmpTransformRect;                boundingRect.set(dirty);                Matrix transformMatrix;                if ((mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {                    Transformation t = attachInfo.mTmpTransformation;                    boolean transformed = getChildStaticTransformation(child, t);                    if (transformed) {                        transformMatrix = attachInfo.mTmpMatrix;                        transformMatrix.set(t.getMatrix());                        if (!childMatrix.isIdentity()) {                            transformMatrix.preConcat(childMatrix);                        }                    } else {                        transformMatrix = childMatrix;                    }                } else {                    transformMatrix = childMatrix;                }                transformMatrix.mapRect(boundingRect);                dirty.set((int) (boundingRect.left - 0.5f),Dirty                        (int) (boundingRect.top - 0.5f),                        (int) (boundingRect.right + 0.5f),                        (int) (boundingRect.bottom + 0.5f));            }            do {                View view = null;                if (parent instanceof View) {                    view = (View) parent;                }                 //  例子中未使用动画,不执行此分支                if (drawAnimation) {                    if (view != null) {                        view.mPrivateFlags |= PFLAG_DRAW_ANIMATION;                    } else if (parent instanceof ViewRootImpl) {                        ((ViewRootImpl) parent).mIsAnimating = true;                    }                }                // If the parent is dirty opaque or not dirty, mark it dirty with the opaque                // flag coming from the child that initiated the invalidate                if (view != null) {                    if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&                            view.getSolidColor() == 0) {                        opaqueFlag = PFLAG_DIRTY;                    }                    if ((view.mPrivateFlags & PFLAG_DIRTY_MASK) != PFLAG_DIRTY) {                        view.mPrivateFlags = (view.mPrivateFlags & ~PFLAG_DIRTY_MASK) | opaqueFlag;                    }                }                //  在do-while循环,View树形结构,依次向上遍历。                //  当前Button父控件是LinearLayout                parent = parent.invalidateChildInParent(location, dirty);                if (view != null) {                    // Account for transform on current parent                    Matrix m = view.getMatrix();                    if (!m.isIdentity()) {                        RectF boundingRect = attachInfo.mTmpTransformRect;                        boundingRect.set(dirty);                        m.mapRect(boundingRect);                        dirty.set((int) (boundingRect.left - 0.5f),                                (int) (boundingRect.top - 0.5f),                                (int) (boundingRect.right + 0.5f),                                (int) (boundingRect.bottom + 0.5f));                    }                }            } while (parent != null);  // 如果当前View的parent非空再次执行        }    }


LinearLayout中不存在invalidateChildInParent,但其父类ViewGroup中包含


ViewGroup.invalidateChildInParent

    public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {        // DRAWN 和  DRAWING_CACHE_VALID 开关是否打开        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {            // 没有动画            if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=                        FLAG_OPTIMIZE_INVALIDATE) {                dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,                        location[CHILD_TOP_INDEX] - mScrollY);                final int left = mLeft;                final int top = mTop;                if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {                    if (!dirty.intersect(0, 0, mRight - left, mBottom - top)) {                        dirty.setEmpty();                    }                }                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;                location[CHILD_LEFT_INDEX] = left;                location[CHILD_TOP_INDEX] = top;                if (mLayerType != LAYER_TYPE_NONE) {                    mPrivateFlags |= PFLAG_INVALIDATED;                    mLocalDirtyRect.union(dirty);                }                return mParent;            } else {            // 有动画,所以当前不执行此分支                mPrivateFlags &= ~PFLAG_DRAWN & ~PFLAG_DRAWING_CACHE_VALID;                location[CHILD_LEFT_INDEX] = mLeft;                location[CHILD_TOP_INDEX] = mTop;                if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {                    dirty.set(0, 0, mRight - mLeft, mBottom - mTop);                } else {                    // in case the dirty rect extends outside the bounds of this container                    dirty.union(0, 0, mRight - mLeft, mBottom - mTop);                }                if (mLayerType != LAYER_TYPE_NONE) {                    mPrivateFlags |= PFLAG_INVALIDATED;                    mLocalDirtyRect.union(dirty);                }                return mParent;            }        }        return null;    }


invalidateChildInParent明天重点介绍



参考资料:

《Android 内核剖析》  第13章    柯元旦





    

原创粉丝点击