【问题标题】:hidden backstack fragments re-shown on configuration change隐藏的 backstack 片段在配置更改时重新显示
【发布时间】:2012-06-22 11:52:45
【问题描述】:

我正在构建一个单活动多片段应用程序。每次交易后我都会添加到后台。经过几次隐藏和显示片段,然后我旋转手机,添加到容器中的所有片段都恢复了,每个片段都在另一个之上。

可能是什么问题?为什么我的活动会显示我之前隐藏的片段?

我正在考虑隐藏所有以前隐藏现在显示的片段,但有没有更“优雅”的方式来做到这一点?

【问题讨论】:

  • 请注意,隐藏的片段已经在容器中保持为不可见。因此,更改配置可能会再次显示它们,因为它们已经存在。

标签: android android-fragments screen-rotation


【解决方案1】:

在每个片段上使用setRetainInstance(true),您的问题就会消失。
警告:将此设置为 true 将更改 Fragments 生命周期。
虽然setRetainInstance(true) 解决了该问题,但在某些情况下您可能不想使用它。 为了解决这个问题,在 Fragment 上设置一个布尔属性并恢复可见性:

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 实例。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。您应该检查活动的 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">
    

    【讨论】:

      【解决方案3】:

      您可能想尝试使用replace() 函数而不是隐藏和显示。当我开始使用Fragments 时遇到了同样的问题,并且使用替换功能确实有助于更好地管理Fragments。这是一个简单的例子:

      fragmentManager.replace(R.id.fragmentContainer, desiredFragment, DESIRED_FRAGMENT_TAG)                                   
                     .addToBackStack(null)
                     .commit();
      

      【讨论】:

        猜你喜欢
        • 2016-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-30
        • 1970-01-01
        • 1970-01-01
        • 2014-09-06
        相关资源
        最近更新 更多