Android Fragment 真正的完全解析(上)
Fragment全解析系列(一):那些年踩过的坑
Fragmentation
FragmentTransaction的commit和commitAllowingStateLoss的区别
项目实践:
Android Fragment 你应该知道的一切
注意事项:
Fragment中启动,Activity中接收结果:使用getActivity().startActivityForResult()
Fragment中启动,Fragment中接收结果:使用startActivityForResult(),且在Activity的onActivityResult()中调用super.onActivityResult()
相信做安卓开发的你,应该都会遇到过Fragment重叠的问题,也许都有自己的解决方法,网上也不少方法,总之良莠不齐吧。在此,我也总结几种解决思路吧。
说之前,还是说一下出现重叠的原因吧,如果是我们自己写代码不太合理,出现的重叠肯定就不废话啦。主要是这两种情况下的重叠:
上述两种情况出现后,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的情况肿么办呢?还是有办法滴,就是在你手机的 “开发者选项” 中,找到 “退出活动不保留任何活动”(因机型不同说法可能不一样) 这一选项并开启,就能很好的模拟这种情况啦。
关键方法: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);
}
如果你的业务允许的话,给每个activity强制竖屏显示。
只需要在相应的activity中声明 android:configChanges=”keyboardHidden|orientation|screenSize”> 即可。
声明这个属性后,当我们切换屏幕时,也就不会在走activity的生命周期方法了,也就不会造成fragment重叠的问题了。
两位博主的解决方案参考:
fragment重叠的完美解决方案
ps:这个值得参考一下
Fragment全解析系列(一):那些年踩过的坑
ps:这篇博客也提到了解决方案,总感觉不太好,可能理解不太深刻吧。
fragment 点击home键在后台一段时间后恢复白屏