9

在 Android 中学习 ViewModel 时,出现了一个问题,感觉 Kotlin 就是要解决这个问题。在下面的代码中,我们可以看到 MutableLiveData 值正在用于编辑值和指标。但是,我们不希望这些可变值暴露给其他任何东西,特别是 Android 生命周期的成员。我们确实希望 Android 生命周期成员能够访问读取值但不能设置它们。因此,下面显示的 3 个公开函数属于 LiveData<> 不可变类型。

是否有更简单或更简洁的方法来公开可以在内部编辑的只读值?这似乎是 Kotlin 避免的:样板冗长。

class HomeListViewModel: ViewModel(){
    //Private mutable data
    private val repositories = MutableLiveData<List<Repo>>()
    private val repoLoadError = MutableLiveData<Boolean>()
    private val loading = MutableLiveData<Boolean>()


    //Exposed uneditable LIveData
    fun getRepositories():LiveData<List<Repo>> = repositories
    fun getLoadError(): LiveData<Boolean> = repoLoadError
    fun getLoadingStatuses(): LiveData<Boolean> = loading

    init{...//Do some stuff to MutableLiveData<>

    }
}

可能类似的非 Android 场景是:

class ImmutableAccessExample{

    private val theThingToBeEditedInternally = mutableListOf<String>()

    fun theThingToBeAccessedPublicly(): List<String> = theThingToBeEditedInternally

    init {
        theThingToBeEditedInternally.add(0, "something")
    }

}
4

4 回答 4

8

我不知道是否可以避免冗长。但是,我以前见过它,它通常被声明为一个属性。

private val _repositories = MutableLiveData<List<Repo>>()
val repositories : LiveData<List<Repo>> 
    get() = _repositories

这是约定,请参阅名称中的文档获取支持属性

如果一个类有两个概念上相同的属性,但一个是公共 API 的一部分,另一个是实现细节,请使用下划线作为私有属性名称的前缀:

于 2018-01-23T16:22:31.207 回答
2

按照这篇文章的想法:

class HomeListViewModel: ViewModel(){
    val repositories: LiveData<List<Repo>> = MutableLiveData()

    init {
        repositories as MutableLiveData
        ...//Do some stuff to repositories
    }
}
于 2019-01-17T22:21:02.740 回答
1

我还没有找到任何优雅的解决方案来解决这个问题,但这就是我处理它的方式。

private val selectedPositionLiveData = MutableLiveData<Int>()
fun getSelectedPosition() = selectedPositionLiveData as LiveData<Int>

通过View公共 getter 方法观察,无需在ViewModel. 我可能喜欢这种方法,因为我的 Java 背景具有显式的 getter,但在我看来,这与任何其他解决方法一样简洁明了。

于 2018-11-01T17:33:07.513 回答
-2

val 没有设置器,因为它是只读的,但如果你想要一个 var,你可以这样做

var repositories = MutableLiveData<List<String>>()
    private set
var repoLoadError = MutableLiveData<Boolean>()
    private set
var loading = MutableLiveData<Boolean>()
    private set

这将为您提供一个私有设置器和一个公共获取器

于 2018-01-23T15:36:48.727 回答