Android 使用SharedReferences在不同生命周期点将字符串保存和恢复到EditText的正确方法?

Android 使用SharedReferences在不同生命周期点将字符串保存和恢复到EditText的正确方法?,android,kotlin,sharedpreferences,Android,Kotlin,Sharedpreferences,我在任何地方都没有找到一个好的明确答案(也许我不擅长搜索?) android有各种事件,这些事件会导致用户丢失EditText内容,除非您在生命周期事件期间保存并还原它——通常使用共享首选项。听起来很简单,但我无法让它在实践中发挥作用;尽管每次活动都会记录EditText内容,但当我导航到另一个应用程序然后再返回时,它不会在我的设备上更新 我让用户在EditText字段中键入序列号。以下是我在活动中所做的: private lateinit var sharedPref: SharedPrefe

我在任何地方都没有找到一个好的明确答案(也许我不擅长搜索?)

android有各种事件,这些事件会导致用户丢失EditText内容,除非您在生命周期事件期间保存并还原它——通常使用共享首选项。听起来很简单,但我无法让它在实践中发挥作用;尽管每次活动都会记录EditText内容,但当我导航到另一个应用程序然后再返回时,它不会在我的设备上更新

我让用户在EditText字段中键入序列号。以下是我在活动中所做的:

private lateinit var sharedPref: SharedPreferences

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // (boilerplate databinding code omitted here)
    sharedPref = getPreferences(Context.MODE_PRIVATE)
}

private fun loadSN() {
    if(sharedPref.contains(PREFERENCE_SN)) {
        binding.serialNumberEditText.setText(sharedPref.getString(PREFERENCE_SN, ""))
        Log.d(TAG, "serialNumberEditText is now ${binding.serialNumberEditText.text.toString()}")
    }
}

private fun saveSN() {
    Log.d(TAG, "saveSN: saving ${binding.serialNumberEditText.text.toString()}")
    with (sharedPref.edit()) {
        putString(PREFERENCE_SN, binding.serialNumberEditText.text.toString())
        apply()
    }
}

override fun onStart() {
    super.onStart()
    loadSN()
}
override fun onPause() {
    super.onPause()
    saveSN()
}

override fun onStop() {
    super.onStop()
    saveSN()
}
override fun onResume() {
    super.onResume()
    loadSN()
}
override fun onRestart() {
    super.onRestart()
    loadSN()
}
导航到其他应用程序然后返回时的日志输出示例:

[navigate away from app]
D/FooActivity: saveSN: saving ABCDE
[^^ return to app here]
D/FooActivity: serialNumberEditText is now ABCDE
D/FooActivity: savePreference was called, restoring ABCDE
D/FooActivity: serialNumberEditText is now ABCDE
D/FooActivity: savePreference was called, restoring ABCDE
D/FooActivity: serialNumberEditText is now ABCDE
D/FooActivity: savePreference was called, restoring ABCDE

但它并没有将ABCDE恢复到编辑文本字段。为什么?

您可以使用viewModel和保存状态模块来完成这项工作。 将此添加到gradle(应用程序级别):

如果您不想使用模块,可以通过以下方式保存状态:

     @Override
        protected void onSaveInstanceState(@NonNull Bundle outState) {
            outState.putString("edit_text", yourEditTextView.getText().toString());
 super.onSaveInstanceState(outState);
        }
并检索该值

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState!=null){
            if (savedInstanceState.containsKey("edit_text")){
                String valueForEditText = savedInstanceState.getString("edit_text");
                yourEditTextView.setText(valueForEditText);
            }
        }

您不需要在“停止时”和“暂停时”中保存状态,只需在“创建时”中定义编辑文本,android将为您执行此操作。

您可以使用viewModel和“保存状态”模块为您执行此操作。 将此添加到gradle(应用程序级别):

如果您不想使用模块,可以通过以下方式保存状态:

     @Override
        protected void onSaveInstanceState(@NonNull Bundle outState) {
            outState.putString("edit_text", yourEditTextView.getText().toString());
 super.onSaveInstanceState(outState);
        }
并检索该值

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState!=null){
            if (savedInstanceState.containsKey("edit_text")){
                String valueForEditText = savedInstanceState.getString("edit_text");
                yourEditTextView.setText(valueForEditText);
            }
        }

您不需要在停止和暂停时保存状态,只需在创建时定义编辑文本,android将为您执行此操作。

框架将在当前布局中为您自动保存
视图
s(包括
编辑文本
s)的状态,但仅当应用程序处于“后台”时。这包括当系统销毁应用程序以回收内存时,视图将恢复原样,但如果用户将应用程序刷走以明确关闭它,或者如果您通过移动到其他
活动来删除布局,则视图将恢复原样。如果希望在用户下次打开该布局时显示相同的数据,则需要自己保存该状态,这确实意味着类似于使用
SharedReferences


从你的日志来看,恢复工作进展顺利?您正在保存
ABCDE
,下次回来时将其设置为
ABCDE
,然后检查
EditText
的内容,并将其设置为
ABCDE
?您看到的是什么,是否还有其他东西可以在该视图上设置数据,比如XML中的数据绑定?系统会在启动前恢复视图状态,因此您的恢复会在启动后进行,但如果存在任何保存的状态,则该状态应与您保存的状态相同。

框架会自动在当前布局中为您保存
视图
的状态(包括
编辑文本
s),但仅当应用程序处于“后台”时。这包括当系统销毁应用程序以回收内存时,视图将恢复原样,但如果用户将应用程序刷走以明确关闭它,或者如果您通过移动到其他
活动来删除布局,则视图将恢复原样。如果希望在用户下次打开该布局时显示相同的数据,则需要自己保存该状态,这确实意味着类似于使用
SharedReferences


从你的日志来看,恢复工作进展顺利?您正在保存
ABCDE
,下次回来时将其设置为
ABCDE
,然后检查
EditText
的内容,并将其设置为
ABCDE
?您看到的是什么,是否还有其他东西可以在该视图上设置数据,比如XML中的数据绑定?系统会在启动前恢复视图状态,因此您的恢复会在启动后进行,但如果有任何保存的状态,它应该与您保存的状态相同。

如果您有一个非常复杂的用户界面,那么我可以理解为什么会感兴趣。但是,如果用户来回导航,我觉得不应该需要单独的ViewModel来维护单个EditText的内容。有没有更简单的方法?简单的解决方案是在活动中@Override onSaveInstanceState()和onRestoreInstanceState。处理活动的暂停和停止调用就足够了。只有在屏幕旋转导致OnDestroy调用时,才能以这种方式维护它。只有当你想在用户关闭应用程序后恢复EditText状态时,你才应该使用共享首选项。事实上,我记得在你的活动类中将EditText定义为变量就足够了,它里面的文本将在Android系统暂停、停止调用后自动恢复。但是我现在不能检查它。如果你有一个非常复杂的用户界面,那么我可以理解为什么这会很有趣。但是,如果用户来回导航,我觉得不应该需要单独的ViewModel来维护单个EditText的内容。有没有更简单的方法?简单的解决方案是在活动中@Override onSaveInstanceState()和onRestoreInstanceState。处理活动的暂停和停止调用就足够了。只有在屏幕旋转导致OnDestroy调用时,才能以这种方式维护它。只有当你想在用户关闭应用程序后恢复EditText状态时,你才应该使用共享首选项。事实上,我记得在你的活动类中将EditText定义为变量就足够了,它里面的文本将在Android系统暂停、停止调用后自动恢复。但我现在不能检查。对,这是奇怪的事情;显然,尽管日志上说我做得不正确,因为
ABCDE
没有恢复到屏幕上的
EditText
。我使用数据绑定来简化对显示数据库元数据的
TextView
元素的引用。
EditText
上有一个
TextChangedListener
,但是