I didn't find a good definitive answer to this anywhere (maybe I'm bad at searching?)
The android Activity Lifecycle has various events that will cause a user to lose EditText contents unless you save and restore it during the lifecycle events - typically, using Shared Preferences. Sounds simple, but I can't get it working in practice; despite logging the EditText contents at each event it's not updating on my device when I navigate to another app and then back again.
I have the user type a serial number in an EditText field. Here's what I'm doing in my activity:
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()
}
Sample log output when navigating to a different app then back again:
[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
Yet it not restoring ABCDE to the EditText field. Why?
The framework will save the state of View
s (including EditText
s) in the current layout for you automatically, but only while the app is in the "background". That includes when the app is destroyed by the system to reclaim memory, the views will be restored as they were - but not if the user swipes the app away to explicitly close it, or if you remove the layout by e.g. moving to a different Activity
. If you want the same data to be displayed next time the user opens that layout, you'll need to persist the state yourself, and that does mean something like using SharedPreferences
.
From your logs it looks like the restoration is happening fine? You're saving ABCDE
, you set it to ABCDE
next time you come back, then you check the contents of the EditText
and it's set to ABCDE
? What are you seeing instead, and is there anything else that sets data on that view, like data binding in the XML? The system restores the view state before onStart
, so your restoration happens after that, but if there is any saved state it should be the same data as what you persisted anyway.