Android LiveData get() 语法如何工作?

Ada*_*itz 6 android kotlin android-livedata

我了解需要在 ViewModel 中为 LiveData创建 getter 和 setter 点,但我希望了解该get()语法在 Android 中的工作原理。

IE:

val isRealtime: LiveData<Boolean>
    get() = _isRealtime
private val _isRealtime = MutableLiveData<Boolean>()
Run Code Online (Sandbox Code Playgroud)

Com*_*are 14

get() 与安卓无关。

val isRealtime: LiveData<Boolean>
    get() = _isRealtime
Run Code Online (Sandbox Code Playgroud)

在这里,get()覆盖了为该isRealtime属性自动生成的 Kotlin getter 函数。因此,它不是返回自己的值,而是返回 的值_isRealtime

就个人而言,我推荐更简单的语法:

private val _isRealtime = MutableLiveData<Boolean>()
val isRealtime: LiveData<Boolean> = _isRealtime
Run Code Online (Sandbox Code Playgroud)

其中任何一个的目的都是保持可变性私有,所以这个类的使用者不会意外地更新MutableLiveData它们自己。

  • @AdamHurwitz:`get()` 有其用途,但适用于更复杂的场景。例如,Android 中的一种模式是在 `Intent` 上为 extras 或在 `Bundle` 上为片段参数创建私有扩展属性。在那里,您将覆盖扩展属性上的`get()` 和`set()` 以路由到正确的getter/setter(例如,`Bundle` 上的`getString()` 和`putString()`)。但是,对于像这样的简单案例,这似乎有点过分了。 (2认同)

Igo*_*jda 8

在 Kotlin 中,我们有多种方法将实时数据从 ViewModel 公开到视图。

class MyViewModel: ViewModel() {

    // Solution 1 - make MutableLiveData public
    // This approach works, but this is a bad idea because
    // view can modify the LiveData values
    val liveDataA1 = MutableLiveData<State>()

    // Solution 2 - let's make LiveData public (expose it instead of MutableLiveData)
    // Now from view perspective this solution looks fine, bu we have a problem,
    // because we need MutableLiveData within ViewModel to put/post new values to
    // the stream (we can't post values to LiveData).
    val liveDataA2 = MutableLiveData<State>() as LiveData<State>

    // Let's capture our requirements:
    // 1. We need to expose (immutable) LiveData to the view,
    // so it cannot edit the data itself.
    // 2. We need to access MutableLiveData from ViewModel to put/post new values.
    // Now, let's consider few appropriate solutions

    // Solution 3
    // Let's name mutable live data using underscore prefix
    private val _liveData3 = MutableLiveData<State>()
    val liveData3 = _liveData3 as LiveData<State>

    // Solution 4
    // We can also perform casting by specifying type for a variable
    // (we can do it because MutableLiveData extends LiveData)
    private val _liveData4 = MutableLiveData<State>()
    val liveData4: LiveData<State> = _liveData4

    // Solution 5
    // Starting from Kotlin 1.4-M.2 we can delegate call to another property
    private val _liveData5 = MutableLiveData<State>()
    val liveData5 by this::_liveData5

    // Solution 6
    // These above solutions work quite well, but we could do even better by
    // defining custom asLiveData extension function.
    private val _liveData6 = MutableLiveData<State>()
    val liveData6 = _liveData6.asLiveData()

    fun <T> MutableLiveData<T>.asLiveData() = this as LiveData<T>
    // Amount of code is similar, but notice that this approach works much better
    // with code completion.

    // Solution 7 (IMO Best)
    // We can also use alternative naming convention - use "mutableLiveData"
    // as variable for mutable live data instead of using underscore prefix
    private val mutableLiveData7 = MutableLiveData<State>()
    val liveData7 = mutableLiveData7.asLiveData()

    // BTW
    // We could also expose getLiveData8() method, but liveData is a state not an action.

    // Solution 9
    // This does not create backing field for the property
    // (more optimised but still Solution 7 is easier to use)
    private val _liveData9 = MutableLiveData<State>()
    val liveData9 get() = _liveData9 as LiveData<State>
}
Run Code Online (Sandbox Code Playgroud)