【问题标题】:Saving a Var during a configuration change在配置更改期间保存 Var
【发布时间】:2020-09-29 16:21:45
【问题描述】:

在屏幕旋转时,我希望保存 var cardcount,这样用户在旋转屏幕时不会重置为第一张闪存卡。

我尝试使用 onSaveInstanceState 和 savedInstanceState.getInt() 来保持旋转时的值,但它不保存值。

我已经看到了这些功能的替代品,但我不确定我是否会为了简单的事情而进入一些深兔子洞,或者我是否完全在错误的海洋中游泳。

我应该研究 ViewModel 和持久性存储、通过配置更改手动接管还是共享首选项?数据是一个变量,在一个片段中。

class Components : Fragment() {

    //Variables to keep track of which card, as well as which side is showing
    private var cardcount = 0
    private var cardfront = true


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        //This is the function to set the image and text for the front and back of the flashard
        fun select_card() {
            card_front.setImageResource(map.getValue(cardcount).image)
            card_back.text = map.getValue(cardcount).text
        }
}

【问题讨论】:

    标签: android kotlin configuration bundles


    【解决方案1】:

    这就是 ViewModel 的用途。

    根据安卓文档:

    ViewModel 类旨在存储和管理与 UI 相关的数据 一种生命周期意识的方式。 ViewModel 类允许数据生存 配置更改,例如屏幕旋转

    https://developer.android.com/topic/libraries/architecture/viewmodel

    【讨论】:

      【解决方案2】:

      如果您还没有使用 ViewModels,那么您绝对不需要使用 SharedPreferences,这可能太多了 - 但这完全取决于您想要什么。

      如果您只想在应用程序“打开”(包括在后台)时保留一个值,那么 onSaveInstanceState() 方法就是为此而生的。在它提供的Bundle 中弹出一个值,当您的片段需要恢复状态时,它将通过onCreateViewonViewCreatedonViewStateRestored 传回...只需在任何一个生命周期回调中取回方便,检查Bundle 不为空(请参阅下一部分!)并使用您用于存储它的相同键获取值。


      如果片段没有恢复之前的状态,您将不会收到传入的捆绑包。您的应用可以随时被系统关闭(比如释放内存) ,所以当它重新启动时,它看起来就像它一直在运行 - 这就是为什么 onSaveInstanceState 被调用,以及为什么你会传入一个包,这样你就可以把所有东西都恢复到它去时的样子进入后台。

      但是,如果用户关闭应用程序,比如将其滑开,下次您打开它时将是一个全新的开始 - 没有状态可以持久,因此您不会获得捆绑包。因此,如果您确实想要在应用程序运行之间保持状态(比如用户选择的语言),您需要使用类似SharedPreferences 的东西来存储一些数据,并将其加载到您的 Fragment 中。


      ViewModels 不会在进程死亡(系统在后台杀死您的应用程序)中幸存下来,因此它们不会像onSavedInstanceState 那样保持状态。它们更多用于诸如配置更改之类的事情,即应用程序将留在前台。你仍然必须能够处理你的状态丢失,并能够重新创建它。还有一些其他库可以扩展 ViewModels 来帮助您处理这个问题,但是......在我看来,只需将 Bundle 用于 Int,保持简单

      绝对不要覆盖配置更改!那是a last resort,你的例子就像,基本的保存实例Bundle用例

      【讨论】:

      • 感谢您提供的信息,我确实尝试了 onSavedInstanceState 但无论出于何种原因它都没有成功。我不确定我是否通过将它放在覆盖函数中并在 onViewCreated 中使用 null 检查来实现它是错误的;但是当我单击构建时,它没有显示任何问题,并且没有保留或恢复变量。我将尝试使用 viewModel,它似乎可以满足我的需求,等等。我读到的所有内容都让我远离了手动配置更改。我会更多地研究捆绑包,我可能做错了什么。再次感谢。
      • 我提到状态的原因是,如果你真的刷掉了应用程序,就没有状态可以恢复——所以这取决于你如何测试它。是的,我通常会在onViewCreated 中进行恢复——这可能值得调试应用程序,并在该方法中设置一个断点,这样你就可以在Bundle 周围戳一下,看看那里实际设置了什么。请注意我对ViewModels 所说的话 - 如果您的进程在后台被破坏,您仍然会丢失您的状态(在您的开发人员选项中打开 Don't keep Activity 以进行测试你的应用如何处理它)
      • 我尝试了应用程序的开发者选项,看看你在说什么。我的 Var 重置回 0。这肯定会被利用,从现在开始,它真正展示了应用程序将如何在后台对 onDestroy 做出反应。有时,当您无法亲眼看到某些东西时,很难理解它。
      • 是的,这正是 Android 的工作方式 - 没有虚拟内存(交换文件、页面文件等),因此您的应用程序可以完全退出内存,并且它必须能够保存和恢复其自己的状态。系统使用Bundle 为您处理其中的一些(保存View 状态、滚动位置、输入到EditTexts 的文本等),onSaveInstanceState 是它允许您添加到该捆绑包的位置,以便您可以保存并恢复其他东西。这个想法是您可以保存简单的值,例如 Ints 和 Strings,并使用它们来重新创建更复杂的状态(包括恢复您的 ViewModel
      • 这应该被标记为这个特定案例的正确答案 IMO。为什么实例化一个 ViewModel 只是为了保存一个变量。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-15
      • 1970-01-01
      相关资源
      最近更新 更多