小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
Activity + Fragment 页面重叠问题
今天在遇到一个很奇怪的问题,我们的软件是用Activity + Fragment构成,在某些场景下,居然发现了有Fragment重叠的现象,究其本质,是因为原来未被销毁,而又新建了一个Fragment,那么这种情况怎么避免呢。
一、 造成问题的原因
根本原因:Activity被销毁并重新创建了,但已经加载过的Fragmen被保存了下来,这时Activity重新创建时又产生了新的Fragment,所以重叠了。
问题场景:
-
横竖屏切换
-
报错之后恢复页面
-
内存不足时Activity销毁
深入探究为什么横竖屏后会产生这个现象呢?
我在网上找到赞同的解释:
当我们旋转屏幕的时候,activity会被销毁并重新创建,并且在销毁之前执行了onSaveInstanceState(Bundle outState)这个方法。这个方法会保存activity的一些信息,其中就包括添加过的fragment,当activity被重新创建时,会初始化其中的变量,这个时候点击底部导航的话会重新去添加fragment,也就导致了重叠的问题。
二、 解决方法
为了模拟这一场景,可在手机 开发者选项-> 应用->不保留活动 模拟场景。
解决方式一:
在Activity回收时不保存状态,这样当Activity销毁时再进入时,就重新加载视图
@Override
protected void onSaveInstanceState(Bundle outState) {
// super.onSaveInstanceState(outState);
}
复制代码
解决方式二:
-
新建Fragment的集合,初始化时加载Fragment
-
在显示
Fragment
时,为每一个Fragment
添加一个tag
-
后在
Activity
的onCreate
中从Bundle
中取出,并在集合中替换相应的Fragment
-
显示
Fragment
时将其它的隐藏 -
如果想记录保存前的Fragment索引
private void showFragment(int position) {
mCurrentFragPosition = position;
}
复制代码
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("position", mCurrentFragPosition);
}
复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mCurrentFragPosition = savedInstanceState.getInt("position");// 恢复崩溃之前fragment所对应的position
Fragment fragment = mFragmentManager.findFragmentByTag("" + mCurrentFragPosition);
if (fragment != null)
mFragments[mCurrentFragPosition] = fragment;
}
}
复制代码