前言
android中我们经常用到inflate方法,今天对这个方法进行一个总结,inflate方法调用方式如下:
调用方法1:
View.inflate(Context context, @LayoutRes int resource, ViewGroup root);
调用方法2:
LayoutInflater.from(Context context).inflate(@LayoutRes int resource, @Nullable ViewGroup root);
调用方法3:
LayoutInflater.from(Context context).inflate(@LayoutRes int resource, ViewGroup root, boolean attachToRoot);
分析
首先看调用方法1:View.inflate(Context context, @LayoutRes int resource, ViewGroup root);
的源码,
public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}
可以看到这个方法就是对调用方法2:LayoutInflater.from(Context context).inflate(@LayoutRes int resource, @Nullable ViewGroup root);
方法的封装,使调用更为简洁。再看它的源码,
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
可以看出,这个方法调用的是inflate(resource, root, root != null);
而这个方法和调用方法3:LayoutInflater.from(Context context).inflate(@LayoutRes int resource, ViewGroup root, boolean attachToRoot);
调用的都是同一个方法。
总结:
- 上述的三种调用方法最终指向的都是
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
- 调用方法1:
View.inflate(Context context, @LayoutRes int resource, ViewGroup root);
和
调用方法2:LayoutInflater.from(Context context).inflate(@LayoutRes int resource, @Nullable ViewGroup root);
如果参数ViewGroup为空就相当于调用方法3:
LayoutInflater.from(context).inflate(resource, null,false);
如果参数ViewGroup不为空就相当于调用方法3:
LayoutInflater.from(context).inflate(resource, root,true);
参数说明
上述三种方法最终调用的都是下边这个方法,所以我们主要分析下边这个方法。
/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
*
* @param resource ID for an XML layout resource to load (e.g.,
* <code>R.layout.main_page</code>)
* @param root Optional view to be the parent of the generated hierarchy (if
* <em>attachToRoot</em> is true), or else simply an object that
* provides a set of LayoutParams values for root of the returned
* hierarchy (if <em>attachToRoot</em> is false.)
* @param attachToRoot Whether the inflated hierarchy should be attached to
* the root parameter? If false, root is only used to create the
* correct subclass of LayoutParams for the root view in the XML.
* @return The root View of the inflated hierarchy. If root was supplied and
* attachToRoot is true, this is root; otherwise it is the root of
* the inflated XML file.
*/
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();
}
}
private @Nullable
View tryInflatePrecompiled(@LayoutRes int resource, Resources res, @Nullable ViewGroup root,
boolean attachToRoot) {
if (!mUseCompiledView) {
return null;
}
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate (precompiled)");
// Try to inflate using a precompiled layout.
String pkg = res.getResourcePackageName(resource);
String layout = res.getResourceEntryName(resource);
try {
Class clazz = Class.forName("" + pkg + ".CompiledView", false, mPrecompiledClassLoader);
Method inflater = clazz.getMethod(layout, Context.class, int.class);
View view = (View) inflater.invoke(null, mContext, resource);
if (view != null && root != null) {
// We were able to use the precompiled inflater, but now we need to do some work to
// attach the view to the root correctly.
XmlResourceParser parser = res.getLayout(resource);
try {
AttributeSet attrs = Xml.asAttributeSet(parser);
advanceToRootNode(parser);
ViewGroup.LayoutParams params = root.generateLayoutParams(attrs);
if (attachToRoot) {
root.addView(view, params);
} else {
view.setLayoutParams(params);
}
} finally {
parser.close();
}
}
return view;
} catch (Throwable e) {
if (DEBUG) {
Log.e(TAG, "Failed to use precompiled view", e);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
return null;
}
/**
* Advances the given parser to the first START_TAG. Throws InflateException if no start tag is
* found.
*/
private void advanceToRootNode(XmlPullParser parser)
throws InflateException, IOException, XmlPullParserException {
// Look for the root node.
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!");
}
}
我们首先看下这几个参数:
- int resource:要加载的XML布局资源的ID。
- ViewGroup root:这个传进的是一个ViewGroup对象。当root不为null,attachToRoot为true时,表示将resource指定的布局添加到root中;当root为null时,不论attachToRoot为true还是为false,不需要将第一个参数所指定的布局添加到任何容器中,同时也表示没有任何容器来来协助第一个参数所指定布局的根节点生成布局参数。
- boolean attachToRoot,这个就是上边说的,用来决定inflate返回的view跟root是否存在父子布局关系。