如何创建可以保存状态的不可为空的 LiveData

Posted

技术标签:

【中文标题】如何创建可以保存状态的不可为空的 LiveData【英文标题】:How to create a non-nullable LiveData that can save state 【发布时间】:2022-01-21 11:42:53 【问题描述】:

当我们有如下的 liveData 时,我们不能 _liveData.value++,因为 value 可以为空。

class MainViewModel(savedStateHandle: SavedStateHandle): ViewModel() 
    private val _liveData: MutableLiveData<Int> =
        savedStateHandle.getLiveData("SomeKey", 0)

    val liveData: LiveData<Int> = _liveData

    fun triggerLiveData() 
        _liveData.value++
    

文章https://proandroiddev.com/improving-livedata-nullability-in-kotlin-45751a2bafb7提供了解决方案,即

@Suppress("UNCHECKED_CAST")
class SafeMutableLiveData<T>(value: T) : LiveData<T>(value) 

  override fun getValue(): T = super.getValue() as T
  public override fun setValue(value: T) = super.setValue(value)
  public override fun postValue(value: T) = super.postValue(value)

但这不支持 savedState。

我们怎样才能得到一个非空的 LiveData 也有已保存状态?

【问题讨论】:

【参考方案1】:

我有一个复制数据但看起来不那么优雅的解决方案

@Suppress("UNCHECKED_CAST")
class SafeMutableLiveData<T: Any>(private val mutableLiveData: MutableLiveData<T>) :
    MutableLiveData<T>(mutableLiveData.value) 

    override fun getValue(): T = mutableLiveData.value as T
    override fun setValue(value: T) 
        super.setValue(value)
        mutableLiveData.value = value
    
    override fun postValue(value: T) 
        super.postValue(value)
        mutableLiveData.postValue(value)
    

用法如下

class MainViewModel(savedStateHandle: SavedStateHandle): ViewModel() 
    private val _liveData: SafeMutableLiveData<Int> =
        SafeMutableLiveData(savedStateHandle.getLiveData("Something", 0))

    val liveData: LiveData<Int> = _liveData

    fun triggerLiveData() 
        _liveData.value++
    

【讨论】:

以上是关于如何创建可以保存状态的不可为空的 LiveData的主要内容,如果未能解决你的问题,请参考以下文章

我们如何保存和恢复 Android StateFlow 的状态?

使用 Laravel ORM 抽象保存新的不可为空的关系,而不会违反数据库完整性约束

使用可为空和不可为空的日期值创建 Blazor 自定义日期选择器组件

C# 8 中的不可为空的引用类型在运行时可以为空吗?

必须初始化不可为空的实例字段“taskTitle”

如何将“任何不可为空的类型”指定为泛型类型参数约束?