好久没有写博客了,=_=…可能工作了,时间确实有点紧张….
我们常用的布局的加载的方法有两种:
View.inflate(context,resId,root);
LayoutInflater.inflate(context,resId,root);
那么这两种之间有什么关系呢?
通过底层的源码来说,其实都是通过LayoutInflate来加载布局的;
那么这两个加载的方式有什么不同吗?
如果我们简单的查看一下源码的话,会发现一个问题就是=_=,View.inflate的实现就是LayoutInflate的inflate方法的实现,源码如下:
public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}
但是这里继续深究:LayoutInflate.inflate(resource,root);
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
这个方法inflate(Resource,root)的实现,其实是LayoutInflate的另一个方法:inflate(resourse,root,root!=null)来完成的,我们继续向下看:
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) + ")");
}
//获取布局文件的解析对象,通过这个对象,可以拿到一些东西
final XmlResourceParser parser = res.getLayout(resource);
try {
//真正的对布局进行一个加载;
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
我们会发现上面的那个方法是其实是一个public访问的;
这里的话,我们整理一下思路,到目前位置,大概的顺序是这样的:
我们注意一点如下:
- View.inflate()传入的root,如果是空的话,在LayoutInflate中的View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)方法中的attachToRoot就为false;
接着我们继续看对布局真正加载的方法: inflate(parser, root, attachToRoot);
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.inflate()的最后一个参数,root
View result = root;
try {
// Look for the root node.
//对xml进行的一个解析操作;
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG &&
type != XmlPullParser.END_DOCUMENT) {
// Empty
}
if (type != XmlPullParser.START_TAG) {
throw new InflateException(parser.getPositionDescription()
+ ": No start tag found!");
}
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
//这里是将布局真正的进行一个加载成一个View对象,但是这个view对象没有LayoutParams属性;
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
ViewGroup.LayoutParams params = null;
if (root != null) {
// Create layout params that match root, if supplied
//根据root提供的上下文环境,对加载的xml属性进行一个读取;
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
//这里表示root不为空,attach为false,这个时候将上面加载出来的布局设置加载好的LayoutParmas
// 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.
//这里表示,如果root,不为null,且,attachToRoot为true;
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.
//root为null的时候,将result=temp,初始化的时候,result=root的
if (root == null || !attachToRoot) {
result = temp;
}
}
}
return result;
}
}
从上面的代码我们可以知道如下:
1、 我们使用View.Inflate()加载出来的布局,如果传入了root,
- 这个加载的xml文件中的属性,会根据root提供的上下文环境进行一个生效
-将传入的xml加载出来的对象直接添加到了root中;
-这方法的返回值为root
如果没有root的话,xml文件的跟布局的layout属性是不会生效的,是包裹内容的大小,此时方法的返回值是加载出来的view;
2、如果我们使用LayoutInflate的 View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)方法来加载布局的时候:
-传入的root,并且attachToRoot为true,和View.inflate加载的效果一样;
-传入root为空和View.inflate的效果一样;
-传入root,并且attachToRoot为false,加载出来的View,不会被添加到root中,但是xml加载出来的View的layout属性的是会根据root提供的环境被设置到加载出来的View中,此时返回的View是xml加载出来的view;