setRetainInstance 已不推荐使用。有什么替代方案?

5

setRetainInstance已过时,有什么替代方法?

我有许多包含许多复杂对象变量的片段。 今天我只有一行代码:setRetainInstance。 下面是完整的代码示例:

public class MyFragment extends Fragment{
    private MyComplicatedCustomClass1 object1;
    private MyComplicatedCustomClass2 object2;
    private MyComplicatedCustomClass3 object3;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        setRetainInstance(true);
    }
}

这已经足够让我不必再在更改配置时(例如更改屏幕旋转)保存和恢复我的对象了。

如果要替换setRetainInstance,您应该在代码中做出哪些改变?

如果可以,请给我一个简短的代码示例。

P.S.

注意: 我可以阅读文档 - 所以请不要用谷歌式的方式回答: "ViewModel是最好的...谷歌推荐...等等..."。 也请不要复制/粘贴来自谷歌文档的文章 - 我可以自己查看。

如果您有具体的工作代码解决方案 - 我将非常感激。

3个回答

6

我在AndroidManifest.xml中设置了configChanges而不是在片段中设置setRetainInstance。当我翻转屏幕时,活动不会销毁我的片段和其中的对象。

<activity android:name=".MyActivity"
      android:configChanges="screenSize|orientation"
      android:label="@string/app_name">

0
谷歌推荐的正确解决方案是使用ViewModel,其中您不仅可以维护(和恢复)状态,还可以异步推送LiveData(或类似内容)。现在还有一种附加的简单半自动化解决方案,即ViewModel Saved State Module
引用以下内容:
当使用此模块时,ViewModel对象通过其构造函数接收SavedStateHandle对象。这个对象是一个键值映射,可以让您将对象写入保存的状态并从中检索对象。这些值在系统杀死进程后持久存在,并通过同一对象保持可用。
因此,您应该始终假定Fragment(及其UI)是临时的,并且将在操作系统最早的便利时销毁。由您确保它不依赖于“神奇保存”状态(例如setRetainInstance),而是以一种基于ViewModel提供的东西来恢复其状态的方式编写您的Fragment。

3
暂时忽略你的讽刺,我想提醒你这不是一个免费编码的网站或服务。在Google文档中有很多样本代码,你的问题很简单(我引用一下):“在我的代码中替换setRetainInstance应该做什么改变?” 你应该使用ViewModel并将状态保存在其中,在观察到状态变化时在Fragment中做出反应。除了查看Google Architecture Samples库之外,还有其他什么方法吗?该库中包含了许多相关示例。 - Martin Marconcini
2
如果你认为有一个神奇的解决方案(除了我已经提供的),那么你会失望的。你有很多“复杂对象”,你懒惰地不想以正确可重用和可测试的方式保存它们?好吧,那就把你的复杂对象保留在UI中,但是别来问是否有神奇的解决方案(因为没有)。保留实例并不是一个解决方案,而是一个hack。如果你从未销毁它,就不需要恢复状态... - Martin Marconcini
问题在于,在运行缓慢的 Android 设备上,从复杂 ViewModel 中重新创建复杂 UI 需要很长时间。例如,用户可能已经打开了自动完成文本视图,然后旋转屏幕,而选项列表却关闭了。而 iOS 系统则免费提供此功能。这就是引起不满的原因所在。 - zaitsman
这确实会“慢”一些,但之前的解决方案并不是销毁片段(保留),这可能会产生其他副作用,我们不会在这里讨论那个问题。Google推荐的解决方案是使用它,或者OP可以自己复制“setRetain”逻辑并处理后果。Google并不太关心“旧/慢”设备,/耸肩 - Martin Marconcini
开发iOS应用的原因是如此之多,这也是为什么它更加美好的原因 :) - zaitsman
是的,特别是你只能在 macOS 上完成它的部分(对于一些人来说这是一场灾难),潜在的99%的开发者被困在 Xcode 中或不得不以某种方式使用它,而且你必须掷骰子才能看到 App Store 的审核是否允许你发布应用程序。 ;) 在不到5年的设备上,Android 的体验没有这样的问题,速度足够快以便及时重建视图。在我用于测试的 iPhone 6s 上也是如此,它非常缓慢,现代应用程序(如果支持)经常因 OOM 错误而崩溃。/耸肩。总之:两个平台都很糟糕。 - Martin Marconcini

-1

你可以使用liveData或其他类型的ViewModel,或者使用arguments来设置类的额外参数。监听器可以在onAttach方法中设置。

如果你经常使用retainInstance,那么可能会有几个内存泄漏问题。

片段不应该太复杂,所以如果你有包含多个复杂类的片段,也许你应该检查一下你的架构。


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