一 首先我们先了解已下Fragment的添加:
1添加Fragment有两种方法,第一就是同replace方式,是相当于在ID为mFramelayout的Framelayout上只有一层,就是Fragment1,通过replace方式会把fragment的生命周期在走一遍,如果有数据的话,会频繁的拉取数据。
而且Fragment绑定的试图一定会被销毁,fragmnet的实例对象不一定会被销毁,那要看有没有添加到回退栈里面。
2通过add方法添加fragment,通过add方式可以添加多个fragment,这个时候我们就可以使用hide()方法和show()方法来切换不同的fragment,好处是,当fragment重新(show)展示出来的时候,原来的数据还保留在fragment,由此得出hide()方法并没有销毁fragment而只是隐藏了fragment。
二 Fragment是怎么造成重叠的:
1.首先我们先添加4个Fragment 到FragmentManager(Fragment管理器)上,通过hide()和show()方法都是可以正常切换的。
2当我们切换到Fragmnet2时,比如mFragment2变量指向的时{Fragmnet2 mFragment2=new Fragment2},这个时候我们按下HOME键,如果长时间没有返回应用或者内寸不足了,系统会回收了改变量的引用,此时mFragment2=null;其实mFragment2是实例还是存在内存中的,只是引用被销毁了,这个时候我们切换到Fragmnet3,通过hide()方法隐藏Fragmnet2,show()方法显示Fragmnet3,但是因为此时的mFragmnet2引用为null,无法使用hide()方法进行隐藏,又因为mFragmnet2的实例有存在内春中,此时就会造成Fragmnet2和Fragmnet3的重叠。如果在次切换到Fragmnet2,因为mFragmnet2=null,所以会再次创建一个新的Fragment添加进去,放到原来的Fragmnet2的位置,后果就是原来的Fragmnet2会一直存在内存中,会一直出现重叠的现象,直到被收回。
3造成以上的原因,还是我们无法找到一开始那个Fragmnet2的实例对象,因为Fragmnet2的引用已经为null,我们可以在add(), fragment的时候添加一个Tag,用它来标识Fragmnet2,当引用为空的时候可以通过Tag来找到Fragmnet2
代码如下:
//添加Fragment
FragmentManager mManager = getSupportFragmentManager();
FragmentTransaction tran = mManager.beginTransaction();
Fragment2 mFragment2=new Fragment2();
tran.add(R.id.mFramelayout,mFragment2,"Fragmnet2");
tran.commit();
在使用的时候我们可以判断一下
if(mFragment2!=null){
tran.hide(Fragment2);
tran.show(Fragment3);
tran.commit();
}else{
mFragment2=(Fragment2)mManager.findFragmentByTag("Fragment2");
tran.hide(Fragment2);
tran.show(Fragment3);
tran.commit();
}
三 最适合的方法是在添加Fragment的时候设置一个Tag值,当引用被销毁了,可以通过Tag来找到该Fragment,然后继续显示和隐藏。
总结:
我们按下HOME键,如果长时间没有返回应用或者内寸不足了,系统会回收了改变量的引用,此时mFragment2=null;其实mFragment2是实例还是存在内存中的,只是引用被销毁了,无法隐藏,就会造成重叠的现象。
原因是我们找不到Fragment的实例对象,因为引用的fragment为null;
我们可以设置一个Tag,用它来标识Fragmnet2,当引用为空的时候可以通过Tag来找到Fragmnet2.
使用replace方法会避免上面说的重叠现象,但是会重复的创建Fragment的对象,因为replace对应的FramenLayout只有一层,
而add方法对应的FramenLayout其实有两层。replace还有个缺点就是会把Fragment的生命周期都走一遍,
如果在生命周期里面有获取数据的话,就会重复的加载和刷新数据,造成不必要的浪费。
四 我写完了。