andorid Fragment你应该知道的以及重叠的解决方案

Android Fragment 真正的完全解析(上)

Fragment全解析系列(一):那些年踩过的坑
Fragmentation

FragmentTransaction的commit和commitAllowingStateLoss的区别

项目实践:

Android Fragment 你应该知道的一切

注意事项:
Fragment中启动,Activity中接收结果:使用getActivity().startActivityForResult()
Fragment中启动,Fragment中接收结果:使用startActivityForResult(),且在Activity的onActivityResult()中调用super.onActivityResult()


fragment重叠的解决方案:

相信做安卓开发的你,应该都会遇到过Fragment重叠的问题,也许都有自己的解决方法,网上也不少方法,总之良莠不齐吧。在此,我也总结几种解决思路吧。

说之前,还是说一下出现重叠的原因吧,如果是我们自己写代码不太合理,出现的重叠肯定就不废话啦。主要是这两种情况下的重叠:

  1. app内存不够被kill,活动被销毁,出现GC
  2. 空指针意外退出应用
  3. 屏幕旋转造成生命周期改变

上述两种情况出现后,Fragment所依附的活动的 onSaveInstanceState会被调用,由源码能看出,此时Fragment的状态会被保存

@Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        Log.i(TAG, "onSaveInstanceState: 保存");
        super.onSaveInstanceState(outState);
    }

app或活动再次被启动后,onCreate方法和onRestoreInstanceState方法会 依次 调用,此时Fragment的状态会被恢复

 @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        Log.i(TAG, "onRestoreInstanceState: 恢复");
        super.onRestoreInstanceState(savedInstanceState);
    }

这时 FragmentManager 管理的 fragment 状态都会恢复,此时你如果在onCreate方法中,不做任何判断的话,还是重新去创建新的Fragment实例,去加载显示,此时重叠现象就会出现啦。
那此时有人就说啦,我的手机性能比较高,不太好复现这种内存不够,出现GC的情况肿么办呢?还是有办法滴,就是在你手机的 “开发者选项” 中,找到 “退出活动不保留任何活动”(因机型不同说法可能不一样) 这一选项并开启,就能很好的模拟这种情况啦。

(1)内存不够导致fragment重叠解决思路:

解决思路一:

关键方法:mFragmentManager.findFragmentByTag
我们在add Fragment时,要添加个tag,如:transaction.add(R.id.fl_container, fragment, tag);

GC之后,Fragment所依附的活动再次启动后,onCreate方法再次执行时,我们根据之前设置的tag去 查找相应Fragment的实例,如果查到了,就用查到的Fragment,否则再去创建相应Fragment的实例。

解决思路二:

关键方法: mFragmentManager.putFragment(outState,“fragment_key”,fragment);
在 onSaveInstanceState 方法被调用时,把不为空的Fragment实例,我们做下保存,在下次执行onCreate方法时,再取出。

 @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        Log.i(TAG, "onSaveInstanceState: 保存");
       if( fragment!=null){
          mFragmentManager.putFragment(outState,"fragment_key",fragment);
       }
        ...
     
        
        //切记,方法要写在super之前
        super.onSaveInstanceState(outState);
    }

GC之后,执行onCreate方法中的super.onCreate(savedInstanceState),savedInstanceState参数是一定不为空的。因此我们可以做如下处理:

 if (savedInstanceState != null) {
            homeFragment = mFragmentManager.getFragment(savedInstanceState, "fragment_key");
             ...
        } else {
            //正常处理
        }

解决思路三(不推荐):

简单粗暴的方案,就是重写onSaveInstanceState方法,然后把super.onSaveInstanceState(outState);方法注释掉。

 @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        Log.i(TAG, "onSaveInstanceState: 保存");
        //super.onSaveInstanceState(outState);
    }

(2)屏幕旋转造成生命周期改变导致fragment重叠解决思路:

解决思路一:

如果你的业务允许的话,给每个activity强制竖屏显示。

解决思路二:

只需要在相应的activity中声明 android:configChanges=”keyboardHidden|orientation|screenSize”> 即可。

 <activity
            android:name=".MainActivity"
            android:configChanges="keyboardHidden|orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

声明这个属性后,当我们切换屏幕时,也就不会在走activity的生命周期方法了,也就不会造成fragment重叠的问题了。


两位博主的解决方案参考:

fragment重叠的完美解决方案
ps:这个值得参考一下

Fragment全解析系列(一):那些年踩过的坑
ps:这篇博客也提到了解决方案,总感觉不太好,可能理解不太深刻吧。

fragment 点击home键在后台一段时间后恢复白屏

发布了82 篇原创文章 · 获赞 131 · 访问量 35万+

猜你喜欢

转载自blog.csdn.net/da_caoyuan/article/details/85096646