如何在返回堆栈中正确保存 Fragments 的实例状态? [英] How to correctly save instance state of Fragments in back stack?

查看:25
本文介绍了如何在返回堆栈中正确保存 Fragments 的实例状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 SO 上发现了许多类似问题的实例,但遗憾的是没有任何答案符合我的要求.

I have found many instances of a similar question on SO but no answer unfortunately meets my requirements.

我有不同的纵向和横向布局,并且我使用了后置堆栈,这既阻止了我使用 setRetainState() 和使用配置更改例程的技巧.

I have different layouts for portrait and landscape and I am using back stack, which both prevents me from using setRetainState() and tricks using configuration change routines.

我在 TextViews 中向用户显示某些信息,这些信息不会保存在默认处理程序中.仅使用活动编写我的应用程序时,以下效果很好:

I show certain information to the user in TextViews, which do not get saved in the default handler. When writing my application solely using Activities, the following worked well:

TextView vstup;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.whatever);
    vstup = (TextView)findViewById(R.id.whatever);
    /* (...) */
}

@Override
public void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    state.putCharSequence(App.VSTUP, vstup.getText());
}

@Override
public void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);
    vstup.setText(state.getCharSequence(App.VSTUP));
}

使用 Fragments,这仅适用于非常特定的情况.具体来说,可怕的是替换一个片段,把它放在后堆栈中,然后在显示新片段时旋转屏幕.据我了解,旧片段在被替换时不会收到对 onSaveInstanceState() 的调用,而是以某种方式与 Activity 保持链接,并且稍后在 onSaveInstanceState() 时调用此方法code>View 不再存在,因此将我的任何 TextView 结果查找为 NullPointerException.

With Fragments, this works only in very specific situations. Specifically, what breaks horribly is replacing a fragment, putting it in the back stack and then rotating the screen while the new fragment is shown. From what I understood, the old fragment does not receive a call to onSaveInstanceState() when being replaced but stays somehow linked to the Activity and this method is called later when its View does not exist anymore, so looking for any of my TextViews results into a NullPointerException.

另外,我发现保留对我的 TextViews 的引用对于 Fragments 不是一个好主意,即使 Activity 没问题> 的.在这种情况下,onSaveInstanceState() 实际上保存了状态,但是如果我在片段隐藏时旋转屏幕两次,问题会再次出现,因为它的 onCreateView() 不会在新实例中被调用.

Also, I found that keeping the reference to my TextViews is not a good idea with Fragments, even if it was OK with Activity's. In that case, onSaveInstanceState() actually saves the state but the problem reappears if I rotate the screen twice when the fragment is hidden, as its onCreateView() does not get called in the new instance.

我想把 onDestroyView() 中的状态保存到一些 Bundle 类型的类成员元素中(它实际上是更多的数据,而不仅仅是一个 TextViewcode>) 并将 that 保存在 onSaveInstanceState() 中,但还有其他缺点.主要是,如果当前显示的是片段,则调用这两个函数的顺序是相反的,因此我需要考虑两种不同的情况.必须有更干净正确的解决方案!

I thought of saving the state in onDestroyView() into some Bundle-type class member element (it's actually more data, not just one TextView) and saving that in onSaveInstanceState() but there are other drawbacks. Primarily, if the fragment is currently shown, the order of calling the two functions is reversed, so I'd need to account for two different situations. There must be a cleaner and correct solution!

推荐答案

要正确保存 Fragment 的实例状态,您应该执行以下操作:

To correctly save the instance state of Fragment you should do the following:

1.在片段中,通过覆盖onSaveInstanceState()保存实例状态并在onActivityCreated()中恢复:

1. In the fragment, save instance state by overriding onSaveInstanceState() and restore in onActivityCreated():

class MyFragment extends Fragment {

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ...
        if (savedInstanceState != null) {
            //Restore the fragment's state here
        }
    }
    ...
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        
        //Save the fragment's state here
    }

}

2.还有重点,在活动中,你必须在onSaveInstanceState()中保存片段的实例,并在中恢复>onCreate().

2. And important point, in the activity, you have to save the fragment's instance in onSaveInstanceState() and restore in onCreate().

class MyActivity extends Activity {

    private MyFragment 

    public void onCreate(Bundle savedInstanceState) {
        ...
        if (savedInstanceState != null) {
            //Restore the fragment's instance
            mMyFragment = getSupportFragmentManager().getFragment(savedInstanceState, "myFragmentName");
            ...
        }
        ...
    }
    
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
            
        //Save the fragment's instance
        getSupportFragmentManager().putFragment(outState, "myFragmentName", mMyFragment);
    }

}

这篇关于如何在返回堆栈中正确保存 Fragments 的实例状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆