看起来MutableLiveData
与LiveData
仅通过公开setValue()
和postValue()
方法有所不同,而LiveData
它们却受到保护。
有什么理由为此更改创建一个单独的类,而不是简单地将这些方法LiveData
本身定义为公共方法?
一般来说,这种继承形式(增加某些方法的可见性是唯一的更改)是否是众所周知的做法,并且在某些情况下它可能有用(假设我们可以访问所有代码)?
看起来MutableLiveData
与LiveData
仅通过公开setValue()
和postValue()
方法有所不同,而LiveData
它们却受到保护。
有什么理由为此更改创建一个单独的类,而不是简单地将这些方法LiveData
本身定义为公共方法?
一般来说,这种继承形式(增加某些方法的可见性是唯一的更改)是否是众所周知的做法,并且在某些情况下它可能有用(假设我们可以访问所有代码)?
Answers:
在LiveData - Android开发者文档,你可以看到,对于LiveData
,setValue()
和postValue()
方法不是公共的。
然而,在MutableLiveData - Android开发者文档,你可以看到,MutableLiveData
扩展LiveData
内部也的两大神奇的方法LiveData
是公开提供这一点,他们setValue()
和postValue()
。
setValue()
:设置值并将其分发给所有活动的观察者,必须从主线程调用。
postValue()
:将任务发布到主线程以覆盖设置的值setValue()
,必须从后台线程调用。
因此,LiveData
是一成不变的。MutableLiveData
是LiveData
它是可变的和线程安全的。
这是整个MutableLiveData.java
文件:
package androidx.lifecycle;
/**
* {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
*
* @param <T> The type of data hold by this instance
*/
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
因此,是的,区别仅在于公开postValue
和setValue
公开。
我能想到的一个用例是使用Kotlin中的Backing Property进行封装。您可以暴露LiveData
你的碎片/活动(UI控制器),即使你可以MutableLiveData
在你的操控ViewModel
类。
class TempViewModel : ViewModel() {
...
private val _count = MutableLiveData<Int>()
val count: LiveData<Int>
get() = _count
public fun incrementCount() = _count.value?.plus(1)
...
}
这样,您的UI控制器将只能观察值而不能对其进行编辑。显然,您的UI控制器可以使用TempViewModel
like的公共方法来编辑值 incrementCount()
。
注意:为了澄清可变/不变的混淆-
data class User(var name: String, var age: Int)
class DemoLiveData: LiveData<User>()
var demoLiveData: LiveData<User>? = DemoLiveData()
fun main() {
demoLiveData?.value = User("Name", 23) // ERROR
demoLiveData?.value?.name = "Name" // NO ERROR
demoLiveData?.value?.age = 23 // NO ERROR
}
_score
啊
MutableLiveData从LiveData扩展。LiveData的受保护方法只能通过自身或子类来解决。因此,在这种情况下,作为LiveData子类的MutableLiveData可以访问这些受保护的方法。
您想要做的是观察实例并查看是否有任何更改。但是同时,您不希望任何“外部人员”更改您正在观察的实例。从某种意义上讲,这会带来问题,因为您希望拥有一个可更改的对象,以更新任何新状态,而不是不可更改,以确保没有人不能更新此实例。这两个功能相互冲突,但是可以通过创建额外的图层来解决。
因此,您要做的是使用可以访问其方法的类扩展LiveData类。子层(在这种情况下为MutableLiveData)能够访问其父级(/超级)的受保护方法。
现在开始创建实例,并创建MutableLiveData的观察者实例。同时,您创建一个引用该实例的LiveData实例。因为MutableLiveData扩展了LiveData,所以任何MutableLiveData实例都是LiveData对象,因此可以由LiveData变量引用。
现在,the俩几乎完成了。您只公开LiveData实例,没有人可以使用其受保护的方法,也不能将其强制转换为它的超级实例(也许在编译时,但不会运行:运行时错误)。而且您将实际的子类实例保持私有,因此只有拥有实例的人员才能使用实例的方法对其进行更改。
//create instance of the sub class and keep this private
private val _name: MutableLiveData<String> = MutableLiveData<String>()
//create an instance of the super class referring to the same instance
val name: LiveData<String> = _name
//assign observer to the super class, being unable to change it
name.value.observe(.....)
现在,超类通知何时应用任何更改。
//change the instance by using the sub class
_name.postValue(...)
//or _name.setValue(...)
Blockquote一般来说,这种继承形式(增加某些方法的可见性是唯一的更改)是一种众所周知的做法吗?在某些情况下它可能有用(假设我们可以访问所有代码)?
是的,这是众所周知的,上面描述的是一种常见的情况。删除观察者模式,仅以set / get形式进行设置就可以从中受益。取决于执行它的位置,最后没有黄金法则。
LiveData
是不可变的,因为客户端无法更改内部状态,因此线程安全