在现在的Android开发中,Fragment属于比较常用的了,在使用Fragment过程中,add、remove和replace这三个方法是比较常用的,也是容易引发歧异的,再加入回退栈的功能就更乱了,那么本文就从实践的角度来说一说这其中的关系。
在开发中,常用的做法是在Activity的布局中放一个FrameLayout,然后以这个FrameLayout为容器,把Fragment当成View(可以把Fragment理解为一个控件或者一个布局)进行切换。我们以此为基础,那么add方法的意思是把一个Fragment加入到这个FrameLayout中,如果连续执行add方法,按照FrameLayout的特性,就相当于在FrameLayout中一层一层的叠View,下面我们来看代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.layout = (FrameLayout) this.findViewById(R.id.content);
int i = 0;
while (i < 10) {
FragmentManager fm = this.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.content, new OneFragment());
ft.commit();
i++;
}
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
System.out.println("当前含有" + this.layout.getChildCount());
}
在代码中的onCreate方法里执行10次往Activity中的FrameLayout添加Fragment,最后打印一下这个FrameLayout中有多少Child:
07-22 00:32:02.648: I/System.out(10480): 当前含有10
由此可见,在这个场景下,add方法就相当于把Fragment层叠的放进FrameLayout中。
remove方法和add方法是相对的,add是一层一层往上放,remove就是从顶上一层一层的往下拿,这里就不再赘述了。
再说replace方法,还是在我们这个FrameLayout的场景中,replace相当于执行了remove和add,会remove相同id的所有Fragment,然后再把这个Fragment放进去,下面来看代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.layout = (FrameLayout) this.findViewById(R.id.content);
int i = 0;
while (i < 10) {
FragmentManager fm = this.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content, new OneFragment());
ft.commit();
i++;
}
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
System.out.println("当前含有" + this.layout.getChildCount());
}
在代码中的onCreate方法里执行10次replace Fragment的操作
,最后打印一下这个FrameLayout中有多少Child:
07-22 00:32:02.648: I/System.out(10480): 当前含有1
由此可见,虽然执行了10次,但是只会有一个Fragment在FrameLayout中。
说完了这个三个方法,再说回退栈的问题。类似于Activity的栈,我们也可以通过用Activity来维护一个Fragment的栈,如果将Fragment加入到回退栈中,那么每次按回退按钮,就会看到上次的Fragment。
说到这里,有一个非常重要的概念,就是add、remove和replace方法和回退栈基本没有关系。这里有一个点非常容易混淆,就是因为add也是一层一层的往FrameLayout里添加Fragment,那么在按回退按钮的时候是不是一层一层的再拿出来呢?笔者这里告诉大家,根本不会,除非加入了回退栈。因为add、remove和replace只是相当于在这个界面层次上做操作,和回退栈没有关系,即使在某些地方看起来很像(回退栈是一个一个的添加进去,按回退的时候会一个一个弹出来)。
那么通过add添加Fragment之后加入回退栈,和通过replace替换Fragment之后加入回退栈有什么不一样呢?
这点就要参照在界面的关系了,add是一层一层往上叠,如果你在其中一层上做了修改,等回退到这一层时,所做的操作会被保留,并且回退的时候会一层一层把Fragment往外拿。replace实际上是替换掉了,那么虽然加入了回退栈,但是会执行销毁视图的方法onDestroyView,回退时会重新执行onCreateView方法重建视图。