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() !&#61; null) {throw new IllegalStateException("The specified child already has a parent. " &#43;"You must call removeView() on the child&#39;s parent first.");}if (!checkLayoutParams(params)) {params &#61; generateLayoutParams(params);}if (preventRequestLayout) {child.mLayoutParams &#61; params;} else {// 前面注释提到的&#xff0c;请求requestLayoutchild.setLayoutParams(params);}// 如果传入-1&#xff0c;直接添加到最后if (index <0) {index &#61; mChildrenCount;}// 添加到ViewGroupaddInArray(child, index);// tell our childrenif (preventRequestLayout) {child.assignParent( this);} else {// 指定添加view的父视图child.mParent &#61; this;}if (child.hasFocus()) {requestChildFocus(child, child.findFocus());}AttachInfo ai &#61; mAttachInfo;if (ai !&#61; null) {boolean lastKeepOn &#61; ai.mKeepScreenOn;ai.mKeepScreenOn &#61; false;// AttachInfo 与 View建立联系child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));if (ai.mKeepScreenOn) {needGlobalAttributesUpdate( true);}ai.mKeepScreenOn &#61; lastKeepOn;}// 可以通过此监听器获得是否有新View被添加if (mOnHierarchyChangeListener !&#61; null) {mOnHierarchyChangeListener .onChildViewAdded(this, child);}if ((child.mViewFlags & DUPLICATE_PARENT_STATE) &#61;&#61; DUPLICATE_PARENT_STATE) {mGroupFlags |&#61; FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE ;}}
疑问&#xff1a;
1. 为什么调用invalidate还调用requestLayout?
2. 为什么先requestLayout, invalidate之后才向ViewGroup中添加View?