首页 文章

Kotlin:只读可变类型访问可变类型的内部变量

提问于
浏览
3

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

Is there an easier or more concise way to expose read only values that can be edited internally? 这似乎是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 回答

  • 1

    我不知道是否有可能避免冗长 . 但是,我以前见过它,它通常被宣布为 property .

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

    这是惯例,参见the doc here中的the doc here

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

  • 3

    我没有找到任何优雅的解决方案,但这是我处理它的方式 .

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

    View 通过公共getter方法观察,并且不需要在 ViewModel 中定义第二个成员 . 由于我的Java背景和明确的getter,我可能更喜欢这种方法,但在我看来,这与其他任何变通方法一样简洁明了 .

  • 0

    遵循this post的想法:

    class HomeListViewModel: ViewModel(){
        val repositories: LiveData<List<Repo>> = MutableLiveData()
    
        init {
            repositories as MutableLiveData
            ...//Do some stuff to repositories
        }
    }
    
  • -1

    val没有setter,因为它只是readonly但如果你想要var,你可以这样做

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

    这将为您提供私人制定者和公共吸气者

相关问题