我正在构建一个包含一个Activity和多个Fragment的应用程序。我在每次交易后将它们添加到返回堆栈中。在隐藏和显示一些Fragment后,我旋转了手机,然后发现所有添加到容器中的片段都被恢复并且每个片段都在另一个片段上面。
可能的问题是什么?为什么我的Activity会显示先前隐藏的片段?
我考虑隐藏所有之前隐藏但现在已显示的片段,但是否有更加“优雅”的方法来解决这个问题?
我正在构建一个包含一个Activity和多个Fragment的应用程序。我在每次交易后将它们添加到返回堆栈中。在隐藏和显示一些Fragment后,我旋转了手机,然后发现所有添加到容器中的片段都被恢复并且每个片段都在另一个片段上面。
可能的问题是什么?为什么我的Activity会显示先前隐藏的片段?
我考虑隐藏所有之前隐藏但现在已显示的片段,但是否有更加“优雅”的方法来解决这个问题?
在每个片段上使用setRetainInstance(true)
,您的问题将会消失。
警告:将其设置为true将更改片段的生命周期。
虽然setRetainInstance(true)
解决了该问题,但有时您可能不想使用它。
要解决这个问题,请在片段上设置一个布尔属性并恢复可见性:
private boolean mVisible = true;
@Override
public void onCreate(Bundle _savedInstanceState) {
super.onCreate(_savedInstanceState);
if (_savedInstanceState!=null) {
mVisible = _savedInstanceState.getBoolean("mVisible");
}
if (!mVisible) {
getFragmentManager().beginTransaction().hide(this).commit();
}
// Hey! no setRetainInstance(true) used here.
}
@Override
public void onHiddenChanged(boolean _hidden) {
super.onHiddenChanged(_hidden);
mVisible = !_hidden;
}
@Override
public void onSaveInstanceState(Bundle _outState) {
super.onSaveInstanceState(_outState);
if (_outState!=null) {
_outState.putBoolean("mVisible", mVisible);
}
}
一旦配置更改(例如屏幕方向),实例将被销毁,但Bundle将被存储并注入到新的Fragment实例中。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
if(savedInstanceState == null){//for the first time
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FragmentExample fragment = new FragmentExample();
fragmentTransaction.add(R.id.layout_main, fragment);
fragmentTransaction.commit();
}else{//savedInstanceState != null
//for configuration change or Activity UI is destroyed by OS to get memory
//no need to add Fragment to container view R.id.layout_main again
//because FragmentManager supported add the existed Fragment to R.id.layout_main if R.id.layout_main is existed.
//here is one different between Fragment and View
}
}
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout_main">
fragmentManager.replace(R.id.fragmentContainer, desiredFragment, DESIRED_FRAGMENT_TAG)
.addToBackStack(null)
.commit();