天天记录 - Android addView源码分析

来源:互联网 发布:渐飞财报数据 编辑:程序博客网 时间:2024/05/21 06:48


    Android把视图显示到屏幕上,从代码角度最终都是调用ViewGroup.addView方法,可以分为两类,一是初始化时添加视图,二是动态添加视图。

1. 从源码角度分析添加视图的流程,以下列出其中4个addView方法

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


2. 以上4个addView方法其最终都会调用以下方法,实现具体操作


    /**     * Adds a child view with the specified layout parameters.     *     * @param child the child view to add     * @param index the position at which to add the child     * @param params the layout parameters to set on the child     */    public void addView(View child, int index, LayoutParams params) {        if (DBG ) {            System. out.println(this + " addView");        }        // 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        // 为什么调用invalidate还调用requestLayout?        requestLayout();        invalidate();        // 为什么先requestLayout, invalidate之后才向ViewGroup中添加View?        addViewInner(child, index, params, false);    }



3. 调用ViewGroup.addViewInner

    private void addViewInner(View child, int index, LayoutParams params,            boolean preventRequestLayout) {        // 此View是否已经添加        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 (!checkLayoutParams(params)) {            params = generateLayoutParams(params);        }        if (preventRequestLayout) {            child.mLayoutParams = params;        } else {             // 前面注释提到的,请求requestLayout            child.setLayoutParams(params);        }        // 如果传入-1,直接添加到最后        if (index < 0) {            index = mChildrenCount;        }                // 添加到ViewGroup        addInArray(child, index);        // tell our children        if (preventRequestLayout) {            child.assignParent( this);        } else {             // 指定添加view的父视图            child.mParent = this;        }        if (child.hasFocus()) {            requestChildFocus(child, child.findFocus());        }        AttachInfo ai = mAttachInfo;        if (ai != null) {            boolean lastKeepOn = ai.mKeepScreenOn;            ai.mKeepScreenOn = false;            // AttachInfo 与 View建立联系            child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));            if (ai.mKeepScreenOn) {                needGlobalAttributesUpdate( true);            }            ai.mKeepScreenOn = lastKeepOn;        }                // 可以通过此监听器获得是否有新View被添加        if (mOnHierarchyChangeListener != null) {            mOnHierarchyChangeListener .onChildViewAdded(this, child);        }        if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {            mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE ;        }    }



疑问:

1. 为什么调用invalidate还调用requestLayout?
2. 为什么先requestLayout, invalidate之后才向ViewGroup中添加View?




原创粉丝点击