fragment使用不当 导致java.lang.IllegalStateException

时间:2022-08-02 20:32:49

错误信息: 

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

信息补充:

使用FragmentActvitiy + Fragment

错误原因:

在fragment类中需要使用inflater加载布局,

1 public class fragmentTest extends Fragment {
2     @Override
3     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
4         inflater.inflate(R.layout.layout_fragment,container);
5         return super.onCreateView(inflater, container, savedInstanceState);
6     }
7 }

特别要注意,inlflate()存在一个三个参数的重载,我们先来查看一下源代码中对第三个参数的说明:

 1 /**
 2      * Inflate a new view hierarchy from the specified xml resource. Throws
 3      * {@link InflateException} if there is an error.
 4      * 
 5      * @param resource ID for an XML layout resource to load (e.g.,
 6      *        <code>R.layout.main_page</code>)
 7      * @param root Optional view to be the parent of the generated hierarchy (if
 8      *        <em>attachToRoot</em> is true), or else simply an object that
 9      *        provides a set of LayoutParams values for root of the returned
10      *        hierarchy (if <em>attachToRoot</em> is false.)
11      * @param attachToRoot Whether the inflated hierarchy should be attached to
12      *        the root parameter? If false, root is only used to create the
13      *        correct subclass of LayoutParams for the root view in the XML.
14      * @return The root View of the inflated hierarchy. If root was supplied and
15      *         attachToRoot is true, this is root; otherwise it is the root of
16      *         the inflated XML file.
17      */
18     public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
19         final Resources res = getContext().getResources();
20         if (DEBUG) {
21             Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
22                     + Integer.toHexString(resource) + ")");
23         }
24 
25         final XmlResourceParser parser = res.getLayout(resource);
26         try {
27             return inflate(parser, root, attachToRoot);
28         } finally {
29             parser.close();
30         }
31     }

在之前的情景中,我们需要在主界面中动态地添加fragment,所以root是不为空的:

1. attachToRoot设为true,则会在加载的布局文件的最外层再嵌套一层root布局。

2. attachToRoot设为false,则root参数失去作用。

3. 在不设置attachToRoot参数的情况下,如果root不为null,attachToRoot参数默认为true。

因为我们要将fragment加载到当前的activity当中,使用false系统会自动将布局加载到合适的层次。因此正确的使用方法是:

inflater.inflate(R.layout.layout_fragment,container,false);

PS:看到一篇博文里讲到对viewroot的一些理解,感觉很有道理。上文中的root其实就是viewroot,它并不是view树的根节点,而是view树的管理者。只是其中有一个变量指向被管理的view树的根节点。一个activity只能有一个viewroot与之绑定