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