For an Android app I have some content that I want to show with a delay. Therefore I'm using a handler.
private lateinit var mHandler: Handler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
linearLayout.isVisible = false
mHandler = Handler()
mHandler.postDelayed({
linearLayout.isVisible = true
}, 1000)
}
How can I save this state (for example in case of rotating the app)? And is it better to use SharedPreferences
or something like this:
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState)
}
I would recommend using the newer ViewModel
component to tackle something like this. The ViewModel
doesn't get destroyed on configuration changes like activities and fragments do, so you can run your Handler
(or Timer
) without fear of losing its state.
class MainViewModel : ViewModel() {
private val layoutVisibility: MutableLiveData<Boolean> by lazy {
MutableLiveData().also {
delayVisibility()
}
}
private fun delayVisibility() {
Timer().schedule(1000) {
layoutVisibility.postValue(true)
}
}
}
class MainActivity : AppCompatActivity() {
private lateinit var model: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
model = ViewModelProviders.of(this)[MainViewModel::class.java]
linearLayout.isVisible = false
model.layoutVisibility.observe(this, Observer<Boolean> { visibility ->
linearLayout.isVisible = visibility == true
})
}
}
You could save the state of the handler—by saving the start time and calculating how much time has elapsed when the activity is recreated—but the ViewModel
architecture seems more intuitive to me.
class MainActivity : AppCompatActivity() {
private lateinit var startTime: Long
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
linearLayout.isVisible = false
var elapsedTime: Long = 0L
if (savedInstanceState != null) {
startTime = savedInstanceState.getLong(KEY_START_TIME, System.currentTimeMillis())
elapsedTime = System.currentTimeMillis() - startTime
} else {
startTime = System.currentTimeMillis()
}
if (elapsedTime >= 1000) {
linearLayout.isVisible = true
} else {
Handler().postDelayed({
linearLayout.isVisible = true
}, 1000 - elapsedTime)
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putLong(KEY_START_TIME, startTime)
}
companion object {
private const val KEY_START_TIME = "start_time"
}
}