savedStateHandle 不保存状态

savedStateHandle not saving State

根据 this 问题,我对我的应用程序做了一些简单的更改,但它没有像我预期的那样工作。

我有一个计时器,它会在计时器结束时发送通知。单击此通知会重新启动activity,删除所有定时器信息,主要存储在viewModel中。出于这个原因,我决定使用 viewModel.

的保存状态

这是我的 viewModel:

class TimerViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {

private val _secondsRemaining = savedStateHandle.getLiveData<Long>(SECONDS_REMAINING)
val secondsRemaining : LiveData<Long>
    get() = _secondsRemaining

这是我在 Fragment 中使用 viewModel 的方法:

private val timerViewModel by viewModels<TimerViewModel>()

当我启动计时器时,我会在时钟的每个滴答声中将剩余的秒数保存在 LiveData 中。当计时器结束时,应用程序发送通知,计时器再次启动,计算一个新的周期:

timer = object : CountDownTimer(timerLengthSeconds * 1000, 1000){
        override fun onFinish(){
            (....)
        }

        override fun onTick(millisUntilFinished: Long) {
            var secondsRemainingInCountdown = millisUntilFinished / 1000

            (...)

            _secondsRemaining.value = secondsRemainingInCountdown
         
        }
    }.start()
}

因此,当计时器结束时,应用程序会发送通知,但计时器已重新启动,剩余的秒数正在更新(我已通过日志检查过)。 当用户单击通知时,activity 被终止并重新启动,并且解释是查看计时器,剩余秒数保存在 LiveData 中。但是当 activity 重新启动时, LiveData 值为空。

我也尝试过将值设置为 10,以防 LiveData 在首次创建时为 null

private val _secondsRemaining = savedStateHandle.getLiveData<Long>(SECONDS_REMAINING, 10)

但是当 activity 重新启动时,我得到 10 作为 LiveData

的值

我想不通原因。

我的第二个问题是我想保存 LiveData 的状态,它存储自定义 class,保存时钟的状态

private val _timerState = MutableLiveData<TimerState>()
val timerState : LiveData<TimerState>
    get() = _timerState

成为这个class:

    sealed class TimerState {

    object OnFocusRunning : TimerState()
    object OnRestRunning : TimerState()
    object OnFocusPaused : TimerState()
    object OnRestPaused : TimerState()
    object Completed : TimerState()
    object RestCompleted : TimerState()
    object NotStarted : TimerState()
}

但我没有成功,因为 TimerState 是自定义 class 而不是原始类型。

当您使用 SavedStateHandle you need to set your values on it 来存储它们时。如果您对特定键使用 getLiveData,那么只要您为该键设置新值,该 LiveData 就会更新。如果您直接在 LiveData 上设置它,您将绕过保存的状态:

class TimerViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {

    // create a LiveData that monitors this key in the saved state
    private val _secondsRemaining = savedStateHandle.getLiveData<Long>(SECONDS_REMAINING)
    val secondsRemaining : LiveData<Long> get() = _secondsRemaining

    // expose a setter that updates the state - this will propagate to the LiveData
    fun setSecondsRemaining(remaining: Long) {
        savedStateHandle[SECONDS_REMAINING] = remaining
    }

}

至于您的其他问题,是的,您可以存储的内容有限,对于自定义 classes,您要么需要 serialise them into a form you can store,要么将它们设为 SerializableParcelable.

但是在你的情况下,由于那个密封的 class 除了是一个类型的实例之外没有做任何特殊的事情,我只是把它变成一个枚举 class - 那些是 Serializable 所以你可以直接把值扔进去!

enum class TimerState {
    OnFocusRunning, OnRestRunning // etc
}