LayoutInflater.inflate方法浅析

来源:互联网 发布:重庆长寿行知学校 编辑:程序博客网 时间:2024/05/16 07:05

在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异常。

0 0
原创粉丝点击