The view. post(Runnable Action) method depends on whether mAttachInfo is empty, so when mAttachInfo is assigned, and where it comes from.

public boolean post(Runnable action) {
    final AttachInfo attachInfo = mAttachInfo;
    if(attachInfo ! =null) {
        return attachInfo.mHandler.post(action);
    }

    // Postpone the runnable until we know on which thread it needs to run.
    // Assume that the runnable will be successfully placed after attach.
    getRunQueue().post(action);
    return true;
}
Copy the code

MAttachInfo is a member variable of View. If you search for mAttachInfo, you will find only one assignment

void dispatchAttachedToWindow(AttachInfo info, int visibility) { mAttachInfo = info; . }Copy the code

AttachInfo info, int Visibility) is not called in the View, so use the ViewGroup

private void addViewInner(View child, int index, LayoutParams params, boolean preventRequestLayout) {
    ...
    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;
    }
    ...
}
Copy the code

So addViewInner looks familiar, yeah, it’s the method that addView eventually calls

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);
}
Copy the code
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);
}
Copy the code
public void addView(View child) {
    addView(child, -1);
}
Copy the code

When is mAttachInfo assigned to be found? Where does mAttachInfo come from?

From the View and ViewGroup code, you can see that mAttachInfo is passed in from parent, The root View is a DecorView, and the DecorView is added to a ViewRootImpl (ViewRootImpl is not a View, but it implements ViewParent, so it has addView methods). So let’s go to ViewParent

public ViewRootImpl(Context context, Display display) { ... mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, context); . }Copy the code

The second answer is also revealed, the creation of mAttachInfo is in the ViewRootImpl constructor, that is, the creation of mAttachInfo, ViewRootImpl.