我了解ViewModel中LiveData的need for creating getter and setter points,但我想了解get()
语法在Android中的工作原理。
即:
val isRealtime: LiveData<Boolean>
get() = _isRealtime
private val _isRealtime = MutableLiveData<Boolean>()
答案 0 :(得分:2)
get()
与Android不相关。
val isRealtime: LiveData<Boolean>
get() = _isRealtime
在这里,get()
覆盖了isRealtime
属性的自动生成的Kotlin getter函数。因此,它不返回自己的值,而是返回_isRealtime
的值。
我个人建议使用更简单的语法:
private val _isRealtime = MutableLiveData<Boolean>()
val isRealtime: LiveData<Boolean> = _isRealtime
这两种方法中的任何一个的目的都是保持可变性的私密性,因此此类消费者不会意外地更新MutableLiveData
。
答案 1 :(得分:1)
在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>
}
答案 2 :(得分:0)
我为此逻辑编写了一个util函数:
import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import kotlin.reflect.KProperty
fun <T> immutable(data: MutableLiveData<T>): Immutable<T> {
return Immutable(data)
}
class Immutable<T>(private val data: MutableLiveData<T>) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): LiveData<T> {
return data
}
}
然后,您可以在任何ViewModel中使用以下方式:
private val _counter: MutableLiveData<Int> = MutableLiveData()
val counter: LiveData<Int> by immutable(_counter)
或简而言之:
private val _counter = MutableLiveData<Int>()
val counter by immutable(_counter)