最近几天在写多个fragment页面,碰到了一个老生常谈,也是非常常见的问题,那就是fragment重叠的问题,我相信这个问题只要是Android的猿人都会碰到,确实是太常见了,解决起来也是非常简单的,我看了看很多博客,用的最多的解决办法是给fragment加个背景颜色,因为fragment默认的背景色是透明的,这样确实能解决重叠的问题,但是只允许在特定的布局下,局限于布局特别的简单,一旦布局复杂了,这样的解决办法是无用的,因为我就碰到过。。。。
一、首先重叠是怎么出现的?
Android管理Fragment的方式主要有两种,这两种各自都有自己的特点:
(1)使用replace来替代,这种方式可以避免重叠的问题,但是每次replace的时候都会重新执行生命周期,当大量获取数据的时候,就会不断的重复加载数据,这显然不是我们需要的使用的方式;
(2)使用add、show、hide方式来管理,这种方式可以避免重复加载数据,但是会导致今天的重点——重叠;
那么出现重叠的原因是什么呢?咱们就得从fragment的特性说起了,fragment是一个小型的activity,基本上是依附在activity上的,所以,当系统内存不足,Fragment 的宿主 Activity 回收的时候,Fragment 的实例并没有随之被回收。Activity 被系统回收时,会主动调用 onSaveInstance() 方法来保存视图层(View Hierarchy),所以当 Activity 通过导航再次被重建时,之前被实例化过的 Fragment 依然会出现在 Activity 中,此时FragmentTransaction 中的相当于又再次 add 了 fragment 进去的,hide()和show()方法对之前保存的fragment已经失效了,所以就出现了重叠。
所以、正应了那句话,万物皆对象,但没有一个对象是十全十美的东西,各有优缺点。
二、解决方案:
出现重叠的解决方案有四种:
(1)视觉冲击:将fragment的背景颜色设置成非透明的,因为fragment默认的背景色是透明的,所以,这可以解决透明的问题,但是这只是给用户的体验感觉,但实际上重叠问题依然存在。
(2)简单粗暴:上面说了导致重叠的原因是Activity被系统回收时,会主动调用onSaveInstance(),通过观察,在onSaveInstance()方法内首先会去调用super,所以,问题就很明朗了,既然他会去保存当前的状态,那么咱们重写onSaveInstance()方法,不让其执行super,重叠问题不就解决了嘛,果然是这样的。
(3)重写onAttachFragment()方法,让新的Fragment指向未被销毁的Fragment;
@Override
public void onAttachFragment(Fragment fragment) {
if (fragment1 == null && fragment instanceof Fragment1)
fragment1 = fragment;
if (fragment2 == null && fragment instanceof Fragment2)
fragment2 = fragment;
if (fragment3 == null && fragment instanceof Fragment3)
fragment3 = fragment;
if (fragment4 == null && fragment instanceof Fragment4)
fragment4 = fragment;
}
(4)其实此方法与第二种方法差不太多,无非就是多几行代码,思路都一样,就是不让其恢复到原来的fragment state,在保存fragment state之前把FragmentManager内的fragment都移除掉。
protected void onSaveInstanceState(Bundle outState) {
FragmentTransaction transaction = fm.beginTransaction();
transaction.remove(fragment1);
transaction.remove(fragment2);
transaction.remove(fragment3);
transaction.remove(fragment4);
transaction.commitAllowingStateLoss();
super.onSaveInstanceState(outState);
}
以上是我总结的四种解决fragment重叠问题的方法,希望对大家有帮助。