隐藏的后退栈片段在配置更改时重新显示

14

我正在构建一个包含一个Activity和多个Fragment的应用程序。我在每次交易后将它们添加到返回堆栈中。在隐藏和显示一些Fragment后,我旋转了手机,然后发现所有添加到容器中的片段都被恢复并且每个片段都在另一个片段上面。

可能的问题是什么?为什么我的Activity会显示先前隐藏的片段?

我考虑隐藏所有之前隐藏但现在已显示的片段,但是否有更加“优雅”的方法来解决这个问题?


请注意,隐藏的片段已经作为不可见的内容保存在容器中。因此,更改配置可能会再次显示它们,因为它们已经存在于其中。 - stdout
3个回答

9

在每个片段上使用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实例中。


3
我遇到过同样的问题。你需要检查你的活动中onCreateView()函数的源代码。
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">


0
你可能想尝试使用`replace()`函数而不是隐藏和显示。当我开始使用片段并使用替换功能时,我遇到了同样的问题,这真的有助于更好地管理片段。这里是一个快速的示例:
fragmentManager.replace(R.id.fragmentContainer, desiredFragment, DESIRED_FRAGMENT_TAG)                                   
               .addToBackStack(null)
               .commit();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接