嵌套Fragment的使用及遇到The specified child already has a parent. You must call removeView()问题的解决

Posted 台风中的橘子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌套Fragment的使用及遇到The specified child already has a parent. You must call removeView()问题的解决相关的知识,希望对你有一定的参考价值。


嵌套Tab在Android应用中用途广泛,之前做过的一些东西都是运用了TabActivity。但是由于在android Developers中说到了“TabActivity was deprecated in API level 13." ,并且建议大家使用Fragment。所以学习了嵌套Fragment的使用,参考了这个博客中的相关思路和代码。

 


在Android Developers中对于Fragment(中文版看这里)的描述:A Fragment represents a behaviors or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running.
简单来说,Fragment就是被嵌入在Activity中用来表现UI的一个可模块化和可重用的组件。Fragment在大屏幕设备中应用可以非常广泛,开发者可以通过自己巧妙的设计让UI更加灵活和美观。

 

创建Fragment
创建Fragment,必须创建一个Fragment的子类。
创建一个自己的Fragment,需要创建一个Fragment的子类。Fragment的生命周期和Activity的生命周期类似,它包含了很多与Activity类似的回调函数。

[java]
public void onCreate (Bundle savedInstanceState) 

public void onCreate (Bundle savedInstanceState)创建fragment的时候调用onCreate()方法
[java]
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 

public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)在第一次绘制UI的时候系统调用该方法,为了绘制UI,返回一个fragment布局的根View。

 


将Fragment添加到Activity的方法
1.在layout文件中声明fragment


[plain]
<FrameLayout 
      android:id="@+id/fragment_container" 
      android:layout_width="fill_parent" 
      android:layout_height="0dip" 
      android:layout_weight="1.0" 
      android:background="#fffab3" > 
  </FrameLayout> 

  <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1.0"
        android:background="#fffab3" >
    </FrameLayout>

 

2.将一个fragment添加到viewgroup中,使用FragmentTransaction添加、替换或者删除fragment。

 

[java]
private void addFragmentToStack(Fragment fragment)  
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
        ft.replace(R.id.fragment_container, fragment); 
        ft.commit(); 
     

private void addFragmentToStack(Fragment fragment)
  FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
  ft.replace(R.id.fragment_container, fragment);
  ft.commit();
 Fragment生命周期


异常分析

 

关于解决 java.lang.IllegalStateException The specified child already has a parent. You must call removeView()的方法

 

在运行调试的时候会发现,在第二次点击一个相同的tab的时候,会出现上述异常。

这个异常说的是,这个特定的child view已经存在一个parent view了,必须让parent view调用removeView()方法。

经过对fragment的生命周期的分析


运行顺序:点击tab1,点击tab2,再点击tab1.

具体fragment的生命周期是:

 

 


对上图进行分析,可以发现,出问题的是viewpager中的view。当切换不同的viewpager(即fragment,每个fragment中装载了一个viewpager)时,调用了startActivity()方法的时候,传入了相同的id,会返回相同的对象。而当我们在第二次调用的时候,传入了相同的id是复用了原来的view,这就导致了view被指定多个parent view。

所以解决办法就是,在使用这个view之前首先判断其是否存在parent view,这调用getParent()方法可以实现。如果存在parent view,那么就调用removeAllViewsInLayout()方法。代码如下:

 

[java]
for (View view : viewList)  
            ViewGroup p = (ViewGroup) view.getParent(); 
            if (p != null)  
                p.removeAllViewsInLayout(); 
             
         

以上是关于嵌套Fragment的使用及遇到The specified child already has a parent. You must call removeView()问题的解决的主要内容,如果未能解决你的问题,请参考以下文章

Android Fragment使用 嵌套Fragments (Nested Fragments) 的使用及常见错误

activity 嵌套一级fragment,一级fragment嵌套二级fragment,在一级fragment中刷新二级fragment中的UI

Fragment 数据懒加载及原理

Android Fragment使用 Toolbar使用及Fragment中的Toolbar处理

两层fragment嵌套时出现空白,(收藏别人的)

Android Toolbar使用及Fragment中的Toolbar处理