LayoutInflater.inflate方法浅析

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值