在Android中,LayoutInflater.inflate()方法一般用于加载布局,相信很多朋友对它已经很熟悉了,但inflate()方法是如何实现的可能有些朋友还不是很清楚,inflater()在使用的时候都有哪些注意事项呢?让我们来简单分析下:
首先不妨来看看Fragment的onCreateView方法,它包含了几个参数,一个LayoutInflater,一个ViewGroup,和一个传递数据用的Bundle。我们可以这样使用inflate方法来为Fragment加载一个布局:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.mylayout,container,false);
return rootView;
}
这里的inflate(int resource, ViewGroup root, boolean attachToRoot)方法包含了三个参数:resource代表要加载布局的id,root代表inflate对象所依托的父容器,boolean attachToRoot表示是否需要将inflate的View依托到root中。inflate还有两个参数的方法,inflate(int resource, ViewGroup root) 其实也是调用了上面的方法。源码如下:
public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
final Resources res = getContext().getResources();
final XmlResourceParser parser = res.getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
可见,inflater首先会将resource所在的XML进行解析,接下来会调用如下方法:
public View inflate(XmlPullParser parse, ViewGroup root, boolean attachToRoot) {
...
final View temp = createViewFromTag(root, name, attrs, false);
ViewGroup.LayoutParams params = null;
if (root != null) {
// Create layout params that match root, if supplied
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
// Set the layout params for temp if we are not
// attaching. (If we are, we use addView, below)
temp.setLayoutParams(params);
}
}
// Inflate all children under temp
rInflate(parser, temp, attrs, true, true);
// We are supposed to attach all the views we found (int temp)
// to root. Do that now.
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.
if (root == null || !attachToRoot) {
result = temp;
}
...
return result;
}
这里只列出了inflate的核心部分,解析xml的代码没有列出。从代码中可以看出,关于root和attachToRoot两个参数存在着如下逻辑:
1、root为空,attachToRoot失去意义,无论它是true还是false,都不会将layout加载到root中,只是返回createViewFromTag()方法所加载的view;
2、如果root不为空,attachToRoot设为true,则会给layout指定一个父布局root(root.addView(temp, params))。
3、如果root不为空,attachToRoot设为false,则只是将root的布局参数设置给要加载的layout(temp.setLayoutParams(params)),这也是最常用的一种情况。当该layout被添加到父view当中时,这些layout属性会自动生效。
通常,我们只需得到一个布局的View,此时,将root参数置空即可,然后可以将该View添加到我们自己的布局中,通过我们自己的布局可以为它设置layout参数。而如果我们想使用一个ViewGroup的layout参数,只需将root参数设为该ViewGroup,attatchToRoot设为false即可。如果还想将这个ViewGroup也加载进来,可以将attatchToRoot设置为true。
另外一点,在构建Fragment的时候,一定要将attachToRoot设置为false,否则,fragment会将root也就是构建Fragment的Activity的布局也加载进来,这个布局又会加载fragment,造成死循环,出现stackOverFlow异常。