您的位置:首页 > 移动开发 > Android开发

android graphic(21)—view tree的创建过程

2016-04-08 14:31 1071 查看
view tree

view tree的构成

view tree

下面这幅图是非常经典的view tree视图,其中叶子节点都是一个个实际的View,而ViewGroup作为View的容器,用来填充ViewGroup或者叶子节点View。



其中,各元素之间都有父子关系,这个父子关系在tree“遍历”的时候非常重要,从子到父,直到根节点(ViewRootImpl的performTraversals())

ViewParent是继承tree中的一个关键接口,定义了作为一个View的parent的所有职责,View用来和其parent交互。

/**
ViewParent----
* Defines the responsibilities for a class that will be a parent of a View.
* This is the API that a view sees when it wants to interact with its parent.
*
*/


ViewGroup继承自View,实现了ViewParent。ViewRootImpl不算是一个View,因为没有继承View,但是实现了ViewParent接口,是该view tree的先祖,和window manager service做交互。



view tree的构成

下面分析一个view tree创建的过程,在/article/8286898.html中分析了activity申请surface的流程,其中主要包括:

1.当Activity调用完setContentView后,其成员mWindow,即PhoneWindow中现存的View如下图所示,



其中,DecorView(父)mDecor是一个FrameLayout,一个ViewGroup,用来“盛放”其他的view组件,例如mContentParent(子),而mContentParent(父)也是一个ViewGroup,用来“盛放”mView(子)。



下面简要分析下上述过程,利用setContentView()添加用户自定义的mView时,

public void setContentView(View view, ViewGroup.LayoutParams params) {
//① mContentParent开始肯定为空,首先执行 installDecor()
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
//②将用户自己的mView添加到mContentParent这个ViewGroup
mContentParent.addView(view, params);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}


private void installDecor() {
if (mDecor == null) {
//创建DecorView mDecor
mDecor = generateDecor();
}
//创建mContentParent ,输入为其父view,mDecor
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}

}

protected ViewGroup generateLayout(DecorView decor) {

View in = mLayoutInflater.inflate(layoutResource, null);
//添加DecorView的子view
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
//contentParent 就是decor的子view
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
}
public View findViewById(int id) {
return getDecorView().findViewById(id);
}


而decor.addView()和mContentParent.addView()最终会调用addViewInner(),在这里会去设置mDecor的子view、用户自定义view的父view为mContentParent。

private void addViewInner(View child, int index, LayoutParams params,
boolean preventRequestLayout) {

// tell our children
if (preventRequestLayout) {
child.assignParent(this);
} else {
//自定义mView的mParent为mContentParent
child.mParent = this;
}

onViewAdded(child);

}


2.在windowmanagerglobal的addView(decor)中,

public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {

//新建一个ViewRootImpl
root = new ViewRootImpl(view.getContext(), display);

view.setLayoutParams(wparams);

mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
//将decor设置到ViewRootImpl中
root.setView(view, wparams, panelParentView);

}


/**
* We have one child
*/
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
//将decor的父view设置为ViewRootImpl
view.assignParent(this);
}
void assignParent(ViewParent parent) {
if (mParent == null) {
mParent = parent;
} else if (parent == null) {
mParent = null;
} else {
throw new RuntimeException("view " + this + " being added, but"
+ " it already has a parent");
}
}


所以经过上面的2步,最终形成的view tree如下图所示,从上到下依次是父子关系,而ViewRootImpl是祖先,用来和window manager service交互。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: