最近项目的最近开发的一个项目中遇到了一种情况,首先来介绍一个项目的首页结构,首页是通过一个底部导航栏去控制,不同Fragment的显示和隐藏。项目在Crash或者长时间处于后台之后。
可能是由于空间不足,导致每次都把主Activity给销毁了,而Fragment给保存下来了,导致了如下图界面
不会退出APP,然后点击返回之后会进入到首页,然后首页的Fragment就出现了重叠现象。
如下图所示:
网上查到的资料说是Fragment重叠的根本原因在于FragmentState没有保存Fragment的显示状态,即
mHidden
,导致页面重启后,该值为默认的false,即show状态,所以导致了Fragment的重叠。
解决方案1:
在fragmentActivity里oncreate方法判断savedInstanceState==null才生成新Fragment,否则不做处理。
public class BaseFragment extends Fragment {
private static final String STATE_SAVE_IS_HIDDEN = "STATE_SAVE_IS_HIDDEN";
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
...
if (savedInstanceState != null) {
boolean isSupportHidden = savedInstanceState.getBoolean(STATE_SAVE_IS_HIDDEN);
FragmentTransaction ft = getFragmentManager().beginTransaction();
if (isSupportHidden) {
ft.hide(this);
} else {
ft.show(this);
}
ft.commit();
}
@Override
public void onSaveInstanceState(Bundle outState) {
...
outState.putBoolean(STATE_SAVE_IS_HIDDEN, isHidden());
}
}
补充:有些小伙伴反应还是会重叠,其实是因为加载根Fragment时没有经过判断的原因,当在类似onCreate
等里加载根Fragment时,需要下面的判断,避免重复加载相同的Fragment:(PS:
add
,replace
情况下,如果没有加入回退栈,则不判断也不会造成重叠;若加入回退栈,则也会造成重叠现象,建议统一判断下)
public class MainActivity ... {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
// 这里一定要在save为null时才加载Fragment,Fragment中onCreateView等生命周里加载根子Fragment同理
// 因为在页面重启时,Fragment会被保存恢复,而此时再加载Fragment会重复加载,导致重叠
if(saveInstanceState == null){
// 正常情况下去 加载根Fragment
}
}
}
解决方案2:在fragmentActivity里重写onSaveInstanceState方法,但不做实现,也就是将super.onSaveInstanceState(outState)注释掉。 这样你Activity销毁了你也不用保存我Fragment的状态了。
@Override
protected void onSaveInstanceState(Bundle outState) {
//注释掉该信息
// super.onSaveInstanceState(outState);
}
但是这两个方案真的神奇的不可思议,在我的测试下,各种情况都正常适用,但是之前从没看到有人提到过该方案,所以如果你发现该方案有我没有考虑到的BUG,请第一时间告诉我!
当遇到问题时,我们如果从源头思考:为什么会发生这个问题? 从源码角度分析问题,可能就会得到一个更好的解决问题的思路!