Android13 ViewGroup addView流程分析

ViewGroup的addView用于向ViewGroup添加中一个子View,有多种重载方法:

1、addView(View child, int index, ViewGroup.LayoutParams params):向ViewGroup中添加一个子View,指定了View位置和LayoutParams参数

2、addView(View child, int index):向ViewGroup中添加一个子View,指定LayoutParams参数

3、addView(View child, ViewGroup.LayoutParams params):向ViewGroup中添加一个子View,指定LayoutParams参数

4、addView(View child):向ViewGroup中添加一个子View

代码如下:

//frameworks/base/core/java/android/view/ViewGroup.java
public abstract class ViewGroup extends View implements ViewParent, ViewManager {


    public void addView(View child) {
        addView(child, -1);
    }


    public void addView(View child, int index) {
        if (child == null) {
            throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
        }
        LayoutParams params = child.getLayoutParams();
        if (params == null) {
            params = generateDefaultLayoutParams();
            if (params == null) {
                throw new IllegalArgumentException(
                        "generateDefaultLayoutParams() cannot return null  ");
            }
        }
        addView(child, index, params);
    }


    public void addView(View child, int width, int height) {
        final LayoutParams params = generateDefaultLayoutParams();
        params.width = width;
        params.height = height;
        addView(child, -1, params);
    }


    public void addView(View child, LayoutParams params) {
        addView(child, -1, params);
    }


    public void addView(View child, int index, LayoutParams params) {
        if (DBG) {
            System.out.println(this + " addView");
        }


        if (child == null) {
            throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
        }


        // addViewInner() will call child.requestLayout() when setting the new LayoutParams
        // therefore, we call requestLayout() on ourselves before, so that the child's request
        // will be blocked at our level
        requestLayout();
        invalidate(true);
        addViewInner(child, index, params, false);
    }
}

上面方法主要处理如下:

1、调用ViewRootImpl的requestLayout方法。

2、调用ViewGroup的invalidate方法。

3、调用ViewGroup的addViewInner方法。

下面分别进行分析:

ViewRootImpl requestLayout

 调用ViewRootImpl的requestLayout方法,请求重新布局:

//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread(); //校验所在线程
            mLayoutRequested = true;
            scheduleTraversals();  //调度视图的遍历和绘制过程
        }
    }
}

ViewRootImpl scheduleTraversals

调用ViewRootImpl的scheduleTraversals方法,调度视图的遍历和绘制过程:

/frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {


    public boolean mTraversalScheduled;
    final Choreographer mChoreographer;


    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }


    final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); //发送一个同步屏障,以确保后续的同步消息在视图绘制完成之前不会执行
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); //下一帧绘制之前执行mTraversalRunnable
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }
}

上面方法主要处理如下:

1、调用Choreographer的postCallback方法,在下一帧绘制之前执行mTraversalRunnable。

2、调用ViewRootImpl的pokeDrawLockIfNeeded方法,请求绘制锁定。

下面分别进行分析:

Choreographer postCallback

调用Choreographer的postCallback方法,用于将一个任务添加到Choreographer的任务队列中,以便在下一帧绘制之前执行。

传入的mTraversalRunnable为TraversalRunnable类,在下一帧绘制前调用TraversalRunnable的run方法,在run方法中调用doTraversal方法:

//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    private boolean mProfile = false;
    final ViewRootHandler mHandler = new ViewRootHandler();
    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);


            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }


            performTraversals();


            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }
}
ViewRootImpl performTraversals

调用ViewRootImpl的performTraversals方法,执行View的三大流程(measure、layout、draw):

Android13 ViewRootImpl performTraversals流程分析-CSDN博客

ViewRootImpl pokeDrawLockIfNeeded

调用ViewRootImpl的pokeDrawLockIfNeeded方法:

//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    final IWindowSession mWindowSession;
    void pokeDrawLockIfNeeded() {
        if (!Display.isDozeState(mAttachInfo.mDisplayState)) {
            // Only need to acquire wake lock for DOZE state.
            return;
        }
        if (mWindowAttributes.type != WindowManager.LayoutParams.TYPE_BASE_APPLICATION) {
            // Non-activity windows should be responsible to hold wake lock by themself, because
            // usually they are system windows.
            return;
        }
        if (mAdded && mTraversalScheduled && mAttachInfo.mHasWindowFocus) {
            try {
                mWindowSession.pokeDrawLock(mWindow);
            } catch (RemoteException ex) {
                // System server died, oh well.
            }
        }
    }
}

调用mWindowSession(IWindowSession)的pokeDrawLock方法,IWindowSession是一个接口,由Session实现:

//frameworks/base/services/core/java/com/android/server/wm/Session.java
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    final WindowManagerService mService;
    public void pokeDrawLock(IBinder window) {
        final long identity = Binder.clearCallingIdentity();
        try {
            mService.pokeDrawLock(this, window);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }
}
WindowManagerService pokeDrawLock

调用WindowManagerService的pokeDrawLock方法,请求绘制锁定:

//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    public void pokeDrawLock(Session session, IBinder token) {
        synchronized (mGlobalLock) {
            WindowState window = windowForClientLocked(session, token, false);
            if (window != null) {
                window.pokeDrawLockLw(mDrawLockTimeoutMillis);
            }
        }
    }
}

ViewGroup invalidate

调用ViewGroup的invalidate方法,进行View的刷新,在UI线程调用:

//frameworks/base/core/java/android/view/ViewGroup.java
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
    private static void invalidate(View root, String parameter) {
        final View view = findView(root, parameter);
        if (view != null) {
            view.postInvalidate();
        }
    }
}

调用View的postInvalidate方法,用于进行View的刷新,在UI线程调用:

//frameworks/base/core/java/android/view/View.java
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
    public void postInvalidate() {
        postInvalidateDelayed(0);
    }
}

调用View的postInvalidateDelayed方法:

//frameworks/base/core/java/android/view/View.java
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
    public void postInvalidateDelayed(long delayMilliseconds) {
        // We try only with the AttachInfo because there's no point in invalidating
        // if we are not attached to our window
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
        }
    }
}

ViewRootImpl dispatchInvalidateDelayed

调用ViewRootImpl的dispatchInvalidateDelayed方法,ViewRootImpl的dispatchInvalidateDelayed,用于验收处理,在dispatchInvalidateDelayed中会通过Handler发送一个延迟消息,最终会调用View.invalidate()方法,在主线程中重新对View进行绘制:

//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    public void dispatchInvalidateDelayed(View view, long delayMilliseconds) {
        Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view);
        mHandler.sendMessageDelayed(msg, delayMilliseconds);
    }
}

发送MSG_INVALIDATE消息,发送的消息在ViewRootHandler的handleMessageImpl中处理:

//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    final class ViewRootHandler extends Handler {
        private void handleMessageImpl(Message msg) {
            switch (msg.what) {
                case MSG_INVALIDATE:
                    ((View) msg.obj).invalidate();
                    break;
            }
        }
    }
}

调用View的invalidate方法:

//frameworks/base/core/java/android/view/View.java
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
    public void invalidate() {
        invalidate(true);
    }


    public void invalidate(boolean invalidateCache) {
        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
    }
}

调用View的invalidateInternal方法:

//frameworks/base/core/java/android/view/View.java
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
            boolean fullInvalidate) {
        if (mGhostView != null) {
            mGhostView.invalidate(true);
            return;
        }


        if (skipInvalidate()) {
            return;
        }


        // Reset content capture caches
        mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
        mContentCaptureSessionCached = false;


        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
            if (fullInvalidate) {
                mLastIsOpaque = isOpaque();
                mPrivateFlags &= ~PFLAG_DRAWN;
            }


            mPrivateFlags |= PFLAG_DIRTY;


            if (invalidateCache) {
                mPrivateFlags |= PFLAG_INVALIDATED;
                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
            }


            // Propagate the damage rectangle to the parent view.
            final AttachInfo ai = mAttachInfo;
            final ViewParent p = mParent;
            if (p != null && ai != null && l < r && t < b) {
                final Rect damage = ai.mTmpInvalRect;
                damage.set(l, t, r, b);
  //调用父类的invalidateChild方法
                p.invalidateChild(this, damage);
            }


            // Damage the entire projection receiver, if necessary.
            if (mBackground != null && mBackground.isProjected()) {
                final View receiver = getProjectionReceiver();
                if (receiver != null) {
                    receiver.damageInParent();
                }
            }
        }
    }
}

ViewGroup invalidateChild

调用ViewParent的invalidateChild方法,ViewParent是一个接口,由ViewGroup实现,调用ViewGroup的invalidateChild方法:

//frameworks/base/core/java/android/view/ViewGroup.java
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
    public final void invalidateChild(View child, final Rect dirty) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null && attachInfo.mHardwareAccelerated) {
            // HW accelerated fast path
            onDescendantInvalidated(child, child);
            return;
        }


        ViewParent parent = this;
        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) != 0;


            // 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();
            // Mark the child as dirty, using the appropriate flag
            // Make sure we do not set both flags at the same time


            if (child.mLayerType != LAYER_TYPE_NONE) {
                mPrivateFlags |= PFLAG_INVALIDATED;
                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
            }


            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) Math.floor(boundingRect.left),
                        (int) Math.floor(boundingRect.top),
                        (int) Math.ceil(boundingRect.right),
                        (int) Math.ceil(boundingRect.bottom));
            }


            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.mPrivateFlags & PFLAG_DIRTY_MASK) != PFLAG_DIRTY) {
                        view.mPrivateFlags = (view.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DIRTY;
                    }
                }


                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) Math.floor(boundingRect.left),
                                (int) Math.floor(boundingRect.top),
                                (int) Math.ceil(boundingRect.right),
                                (int) Math.ceil(boundingRect.bottom));
                    }
                }
            } while (parent != null);
        }
    }
}

ViewGroup addViewInner

调用ViewGroup的addViewInner方法:

//frameworks/base/core/java/android/view/ViewGroup.java
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
    private void addViewInner(View child, int index, LayoutParams params,
            boolean preventRequestLayout) {


        if (mTransition != null) {
            // Don't prevent other add transitions from completing, but cancel remove
            // transitions to let them complete the process before we add to the container
            mTransition.cancel(LayoutTransition.DISAPPEARING);
        }


        if (child.getParent() != null) {
            throw new IllegalStateException("The specified child already has a parent. " +
                    "You must call removeView() on the child's parent first.");
        }


        if (mTransition != null) {
            mTransition.addChild(this, child);
        }


        if (!checkLayoutParams(params)) {
            params = generateLayoutParams(params);
        }


        if (preventRequestLayout) {
            child.mLayoutParams = params;
        } else {
            child.setLayoutParams(params);
        }


        if (index < 0) {
            index = mChildrenCount;
        }


        addInArray(child, index);


        // tell our children
        if (preventRequestLayout) {
            child.assignParent(this);
        } else {
            child.mParent = this;
        }
        if (child.hasUnhandledKeyListener()) {
            incrementChildUnhandledKeyListeners();
        }


        final boolean childHasFocus = child.hasFocus();
        if (childHasFocus) {
            requestChildFocus(child, child.findFocus());
        }


        AttachInfo ai = mAttachInfo;
        if (ai != null && (mGroupFlags & FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW) == 0) {
            boolean lastKeepOn = ai.mKeepScreenOn;
            ai.mKeepScreenOn = false;
            child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
            if (ai.mKeepScreenOn) {
                needGlobalAttributesUpdate(true);
            }
            ai.mKeepScreenOn = lastKeepOn;
        }


        if (child.isLayoutDirectionInherited()) {
            child.resetRtlProperties();
        }


        dispatchViewAdded(child);


        if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
            mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE;
        }


        if (child.hasTransientState()) {
            childHasTransientStateChanged(child, true);
        }


        if (child.getVisibility() != View.GONE) {
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }


        if (mTransientIndices != null) {
            final int transientCount = mTransientIndices.size();
            for (int i = 0; i < transientCount; ++i) {
                final int oldIndex = mTransientIndices.get(i);
                if (index <= oldIndex) {
                    mTransientIndices.set(i, oldIndex + 1);
                }
            }
        }


        if (mCurrentDragStartEvent != null && child.getVisibility() == VISIBLE) {
            notifyChildOfDragStart(child);
        }


        if (child.hasDefaultFocus()) {
            // When adding a child that contains default focus, either during inflation or while
            // manually assembling the hierarchy, update the ancestor default-focus chain.
            setDefaultFocus(child);
        }


        touchAccessibilityNodeProviderIfNeeded(child);
    }
}
  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值