WMS:应用DecorView窗口添加布局

android12-release


1、应用添加布局

onCreate时,setContentView()设置layoutResID(xml布局文件),最终调用到PhoneWindow.java#setContentView()

在这里插入图片描述

2、DecorView初始化

如果mDecor也就是DecorView不存在,就创建一个DecorView;如果mContentParent不存在,就使用mDecor创建一个mContentParent

ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT)
其中ID_ANDROID_CONTENT = com.android.internal.R.id.content
所以android.R.id.content来自DecorViewmContentParent仅仅是DecorView的一个子View。setContentView()设置layoutResID布局添加在mContentParent

在这里插入图片描述

3、LayoutInflater解析布局xml文件

rInflateChildren()与rInflate() 循环层层解析xml,添加相应View

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
    
    
    final Resources res = getContext().getResources();
    if (DEBUG) {
    
    
        Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
              + Integer.toHexString(resource) + ")");
    }

    View view = tryInflatePrecompiled(resource, res, root, attachToRoot);
    if (view != null) {
    
    
        return view;
    }
    XmlResourceParser parser = res.getLayout(resource);
    try {
    
    
        return inflate(parser, root, attachToRoot);
    } finally {
    
    
        parser.close();
    }
}

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    
    
    synchronized (mConstructorArgs) {
    
    
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");

        final Context inflaterContext = mContext;
        final AttributeSet attrs = Xml.asAttributeSet(parser);
        Context lastContext = (Context) mConstructorArgs[0];
        mConstructorArgs[0] = inflaterContext;
        View result = root;

        try {
    
    
            advanceToRootNode(parser);
            final String name = parser.getName();

            if (DEBUG) {
    
    
                System.out.println("**************************");
                System.out.println("Creating root view: "
                        + name);
                System.out.println("**************************");
            }

            if (TAG_MERGE.equals(name)) {
    
    
                if (root == null || !attachToRoot) {
    
    
                    throw new InflateException("<merge /> can be used only with a valid "
                            + "ViewGroup root and attachToRoot=true");
                }

                rInflate(parser, root, inflaterContext, attrs, false);
            } else {
    
    
                // Temp is the root view that was found in the xml
                final View temp = createViewFromTag(root, name, inflaterContext, attrs);

                ViewGroup.LayoutParams params = null;

                if (root != null) {
    
    
                    if (DEBUG) {
    
    
                        System.out.println("Creating params from root: " +
                                root);
                    }
                    // Create layout params that match root, if supplied
                    params = root.generateLayoutParams(attrs);
                    if (!attachToRoot) {
    
    
                        // Set the layout params for temp if we are not
                        // attaching. (If we are, we use addView, below)
                        temp.setLayoutParams(params);
                    }
                }

                if (DEBUG) {
    
    
                    System.out.println("-----> start inflating children");
                }

                // Inflate all children under temp against its context.
                rInflateChildren(parser, temp, attrs, true);

                if (DEBUG) {
    
    
                    System.out.println("-----> done inflating children");
                }

                // We are supposed to attach all the views we found (int temp)
                // to root. Do that now.
                if (root != null && attachToRoot) {
    
    
                    root.addView(temp, params);
                }

                // Decide whether to return the root that was passed in or the
                // top view found in xml.
                if (root == null || !attachToRoot) {
    
    
                    result = temp;
                }
            }

        } catch (XmlPullParserException e) {
    
    
            final InflateException ie = new InflateException(e.getMessage(), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
        } catch (Exception e) {
    
    
            final InflateException ie = new InflateException(
                    getParserStateDescription(inflaterContext, attrs)
                    + ": " + e.getMessage(), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
        } finally {
    
    
            // Don't retain static reference on context.
            mConstructorArgs[0] = lastContext;
            mConstructorArgs[1] = null;

            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }

        return result;
    }
}

final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs,
        boolean finishInflate) throws XmlPullParserException, IOException {
    
    
    rInflate(parser, parent, parent.getContext(), attrs, finishInflate);
}

void rInflate(XmlPullParser parser, View parent, Context context,
        AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
    
    

    final int depth = parser.getDepth();
    int type;
    boolean pendingRequestFocus = false;

    while (((type = parser.next()) != XmlPullParser.END_TAG ||
            parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
    
    

        if (type != XmlPullParser.START_TAG) {
    
    
            continue;
        }

        final String name = parser.getName();

        if (TAG_REQUEST_FOCUS.equals(name)) {
    
    
            pendingRequestFocus = true;
            consumeChildElements(parser);
        } else if (TAG_TAG.equals(name)) {
    
    
            parseViewTag(parser, parent, attrs);
        } else if (TAG_INCLUDE.equals(name)) {
    
    
            if (parser.getDepth() == 0) {
    
    
                throw new InflateException("<include /> cannot be the root element");
            }
            parseInclude(parser, context, parent, attrs);
        } else if (TAG_MERGE.equals(name)) {
    
    
            throw new InflateException("<merge /> must be the root element");
        } else {
    
    
            final View view = createViewFromTag(parent, name, context, attrs);
            final ViewGroup viewGroup = (ViewGroup) parent;
            final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
            rInflateChildren(parser, view, attrs, true);
            viewGroup.addView(view, params);
        }
    }

    if (pendingRequestFocus) {
    
    
        parent.restoreDefaultFocus();
    }

    if (finishInflate) {
    
    
        parent.onFinishInflate();
    }
}

4、ViewGroup添加子View

  • View[] mChildren :存放子节点View,ARRAY_CAPACITY_INCREMENT = 12 12节点扩容
  • mChildrenCount :mChildren 数组中的有效子项数,其余项应为 null 或不被视为子项
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);
}

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);
}

private void addInArray(View child, int index) {
    
    
    View[] children = mChildren;
    final int count = mChildrenCount;
    final int size = children.length;
    if (index == count) {
    
    
        if (size == count) {
    
    
            mChildren = new View[size + ARRAY_CAPACITY_INCREMENT];
            System.arraycopy(children, 0, mChildren, 0, size);
            children = mChildren;
        }
        children[mChildrenCount++] = child;
    } else if (index < count) {
    
    
        if (size == count) {
    
    
            mChildren = new View[size + ARRAY_CAPACITY_INCREMENT];
            System.arraycopy(children, 0, mChildren, 0, index);
            System.arraycopy(children, index, mChildren, index + 1, count - index);
            children = mChildren;
        } else {
    
    
            System.arraycopy(children, index, children, index + 1, count - index);
        }
        children[index] = child;
        mChildrenCount++;
        if (mLastTouchDownIndex >= index) {
    
    
            mLastTouchDownIndex++;
        }
    } else {
    
    
        throw new IndexOutOfBoundsException("index=" + index + " count=" + count);
    }
}

5、时序图

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_23452385/article/details/132114917