美文网首页
安卓 warning (一):LayoutInflater

安卓 warning (一):LayoutInflater

作者: autisticBoy | 来源:发表于2018-12-28 13:13 被阅读0次

    正常使用LayoutInflater时传root为null,会出现以下报错

    Avoid passing null as the view root (needed to resolve layout parameters on the inflated layout's root element) less... (Ctrl+F1)
    When inflating a layout, avoid passing in null as the parent view, since otherwise any layout parameters on the root of the inflated layout will be ignored. More info: http://www.doubleencore.com/2013/05/layout-inflation-as-intended

    意思是不要传root 为Null, 不然最外层得layout参数会失效

    源码

    public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
        synchronized (mConstructorArgs) {
            final AttributeSet attrs = Xml.asAttributeSet(parser);
            mConstructorArgs[0] = mContext;
            View result = root;
            try {
                int type;
                while ((type = parser.next()) != XmlPullParser.START_TAG &&
                        type != XmlPullParser.END_DOCUMENT) {
                }
                if (type != XmlPullParser.START_TAG) {
                    throw new InflateException(parser.getPositionDescription()
                            + ": No start tag found!");
                }
                final String name = parser.getName();
                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, attrs);
                } else {
                    View temp = createViewFromTag(name, attrs);
                    ViewGroup.LayoutParams params = null;
                    if (root != null) {
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            temp.setLayoutParams(params);
                        }
                    }
                    rInflate(parser, temp, attrs);
                    if (root != null && attachToRoot) {
                        root.addView(temp, params);
                    }
                    if (root == null || !attachToRoot) {
                        result = temp;
                    }
                }
            } catch (XmlPullParserException e) {
                InflateException ex = new InflateException(e.getMessage());
                ex.initCause(e);
                throw ex;
            } catch (IOException e) {
                InflateException ex = new InflateException(
                        parser.getPositionDescription()
                        + ": " + e.getMessage());
                ex.initCause(e);
                throw ex;
            }
            return result;
        }
    }
    

    不难分析得以下结论

    1. 如果root为null,attachToRoot将失去作用,设置任何值都没有意义。
    2. 如果root不为null,attachToRoot设为true,则会给加载的布局文件的指定一个父布局,即root。
    3. 如果root不为null,attachToRoot设为false,则会将布局文件最外层的所有layout属性进行设置,当该view被添加到父view当中时,这些layout属性会自动生效。
    4. 在不设置attachToRoot参数的情况下,如果root不为null,attachToRoot参数默认为true。

    例子验证

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
            LayoutInflater inflater = LayoutInflater.from(this);
            inflater.inflate(R.layout.linearlayout, ll,true);
    }
    

    这是可以的,但是 如果 我这么写

    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
            LayoutInflater inflater = LayoutInflater.from(this);
            View view = inflater.inflate(R.layout.linearlayout, ll, true);
            ll.addView(view);
        }
    

    就是错的

    java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

    已经有了父布局,但是如果我把attachToRoot 设置为false, 第二个就不会报错,且效果与true时的第一个一样 ,但是f为false时第一段代码无法将子布局加入

    为什么activity中根节点宽高属性会生效

    大部分情况下我们一个Activity页面由两部分组成(Android的版本号和应用主题会影响到Activity页面组成,这里以常见页面为例),我们的页面中有一个顶级View叫做DecorView,DecorView中包含一个竖直方向的LinearLayout,LinearLayout由两部分组成,第一部分是标题栏,第二部分是内容栏,内容栏是一个FrameLayout,我们在Activity中调用setContentView就是将View添加到这个FrameLayout中,所以给大家一种错觉仿佛Activity的根布局很特殊,其实不然。

    相关文章

      网友评论

          本文标题:安卓 warning (一):LayoutInflater

          本文链接:https://www.haomeiwen.com/subject/uayslqtx.html