设备旋转后,带有setRetainInstanceState(true)的DialogFragment未显示。

15
我有一个关于DialogFragment的问题。我正在尝试制作一个对话框,在设备旋转后保持其状态。此对话框引用了许多诸如适配器和其他较重对象之类的东西,如果可能的话,我需要在旋转时保持它们的状态,而无需使每个引用都可序列化或可保存,以便在重新创建原始活动时使用onSaveInstanceState进行保存和恢复。

我注意到DialogFragment上有一个名为setRetainInstance(boolean)的方法,允许您在重新创建活动时保留对话片段实例。然而,当我现在旋转设备时,对话框不再显示。我知道可以从活动的FragmentManager中获取它,但我找不到重新显示它的方法。对此有什么建议吗?

谢谢, Mihai


1
也许这可以帮助你:https://dev59.com/kmsy5IYBdhLWcg3w6iNZ - Gunnar Karlsson
我在这里看到一个更大的概念性问题。在安卓文档中,setFragmentInstance 是这样写的:“控制是否在 Activity 重新创建时保留片段实例(例如来自配置更改)。这只能用于不在后退堆栈中的片段。如果设置,则当活动重新创建时,片段生命周期会稍有不同”。这个问题是因为对话框片段在后退堆栈中吗? - Swapnil
2个回答

24

以下是需要完成的几个步骤:

  1. 使用实例工厂方法来初始化一个 DialogFragment 实例,如下所示:

    public static MyDialogFragment newInstance(MyModel model) {
        MyDialogFragment myDialogFragment = new MyDialogFragment();
        Bundle bundle = new Bundle();
        bundle.putSerializable("MODEL", model);
        myDialogFragment .setArguments(bundle);
        return myDialogFragment;
    }
    
  2. 在onCreate中加入setRetainInstance(true),可以使得在片段中声明的所有引用在原始活动重新创建后被保留。

  3. @Override
    public void onCreate(Bundle icicle) {
        this.setCancelable(true);
        setRetainInstance(true);
        super.onCreate(icicle);
    
    }
    
  4. 通过这样做避免旋转时消失

  5. @Override
    public void onDestroyView() {
        if (getDialog() != null && getRetainInstance())
            getDialog().setDismissMessage(null);
        super.onDestroyView();
    

  6. 使用以下方式获取你的对象

    (MyModel) getArguments().getSerializable("MODEL")
    

感谢@ricky888的回答,但由于我正在创建一个对话框片段实例并在对话框片段的构造函数中传递一些东西,例如列表适配器和其他重要数据,我想避免序列化,并考虑使用set retain instance state,以便对话框片段不会在旋转时重新创建。因此,我认为通过使用set retain instance state,我将拥有与旋转之前相同的对话框片段-这意味着对话框片段没有在旋转时与活动及其片段一起重新创建。是这种情况吗? - r1k0
setRetainInstance - 控制片段实例是否在 Activity 重新创建(例如从配置更改)时保留。所以答案是肯定的。只需像我上面提到的那样将它们放入 bundle 中,您将跨旋转保留所有内容的相同实例。 - ricky888
事实上,正确的答案涉及序列化,因此我们重新设计了片段,使其数据密度较小,以便能够在配置更改时保持其状态,正如@ricky888所建议的那样。 - r1k0

0

如果您按照以下步骤操作,对话框片段应该会自动保留:

  1. 如果您调用了Activity的onSaveInstanceState()函数,请务必调用super函数!!!在我的情况下,这是关键。还要确保您在片段中做同样的事情。
  2. 如果您使用了setRetainInstance,则需要手动存储值。否则,在大多数情况下,您不必担心它。如果您正在做一些更复杂的事情,则可能需要setRetainInstance(true),但通常可以忽略它。
  3. 有些人抱怨支持库中存在错误,会在不应发送消息时发送dismiss消息。最新的支持库似乎已经修复了这个问题,所以您不需要担心它。

2
关于#2,我认为你在句子开头的意思是“如果你不使用setRetainInstance...”,否则你就必须存储和恢复值。 - android developer

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