fragment使用不当 导致java.lang.IllegalStateException
错误信息:
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与之绑定。