我在SO上找到了很多类似问题的例子,但不幸的是,没有一个答案符合我的要求.

我有不同的纵向和横向布局,我使用后堆栈,这既防止我使用setRetainState()和使用配置更改 routine 的技巧.

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

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));
}

对于Fragment,这只适用于非常特定的情况.具体来说,令人震惊的是替换一个片段,将其放入后堆栈,然后在显示新片段时旋转屏幕.据我所知,旧片段在被替换时不会收到对onSaveInstanceState()的调用,但会以某种方式与Activity保持链接,而这个方法会在其View不再存在时被调用,因此在NullPointerException中查找我的TextView个结果中的任何一个.

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

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

推荐答案

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

1.在片段中,通过覆盖onSaveInstanceState()保存实例状态,并在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.important point,在活动中,您必须在onSaveInstanceState()中保存片段的实例,在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);
    }

}

Android相关问答推荐

使用StateFlow从房间到UiState的流程列表

Jetpack编写:通过viewModels()vs viewModel View ModernName()'

如何从Android 12的来电中获取电话号码?

OverridePendingTransition已弃用,我该怎么办?

ERR_SSL_VERSION_OR_CIPHER_MISMATCH - Android Webview

在 Bash 脚本中使用 XMLLINT 解析 XML 单元测试文件,并将其放入数组中以表示成功和失败

如何在 compose android中将图像覆盖在另一个图像上

为什么我的 APK 中包含来自旧版 Android 支持库的类?

在本地通知中设置自定义声音

如何仅使用您的 Android 应用程序定位平板电脑?

具有管理员权限的 Kotlin 中的多用户系统

DatePickerDialog (Android/Kotlin) 的两个问题

Android 模拟器 Wifi 连接没有互联网

如何在 Jetpack Compose 中创建无限pager

Jetpack 将 Grid 与基于大小的自适应列数组合在一起

找不到(包名称).在以下位置搜索:

如何在 Android 应用程序未激活/未聚焦时显示视图?

可组合的可见性不随状态变化而变化

Jetpack Compose Material3 - switch 标签

现代Android中的后台处理