为什么有一个单独的 LiveData 的 MutableLiveData 子类?
Why there's a separate MutableLiveData subclass of LiveData?
看起来 MutableLiveData
与 LiveData
的区别仅在于使 setValue()
和 postValue()
方法 public,而在 LiveData
中它们受到保护。
为什么要为此更改单独 class 而不是简单地将这些方法定义为 LiveData
本身中的 public?
一般来说,这种形式的继承(增加某些方法的可见性是唯一的变化)是一种众所周知的做法吗?它在哪些场景中可能有用(假设我们可以访问所有代码)?
在LiveData - Android Developer Documentation中,可以看到对于LiveData
、setValue()
& postValue()
方法不是public.
然而,在MutableLiveData - Android Developer Documentation中,您可以看到,MutableLiveData
在内部扩展了LiveData
,而且LiveData
的两个魔术方法是publicly 可用,它们是 setValue()
& postValue()
.
setValue()
:设置值并将值分发给所有活跃的观察者,必须从主线程.
调用
postValue()
: post 主线程的任务覆盖 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
public.
我能想起的一个用例是在 Kotlin 中使用 Backing Property 进行封装。
您可以将 LiveData
公开给您的 Fragment/Activity(UI 控制器),即使您可以在 ViewModel
class 中使用 MutableLiveData
进行操作。
class TempViewModel : ViewModel() {
...
private val _count = MutableLiveData<Int>()
val count: LiveData<Int>
get() = _count
public fun incrementCount() = _count.value?.plus(1)
...
}
这样您的 UI 控制器将只能观察值而不能编辑它们。显然,您的 UI 控制器可以使用 TempViewModel
的 public 方法编辑值,例如 incrementCount()
.
注:澄清mutable/immutable困惑-
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
}
MutableLiveData 是从 LiveData 扩展而来的。 LiveData 的受保护方法只能由 self 或 subclasses 寻址。因此在这种情况下,作为 LiveData 的子 class 的 MutableLiveData 可以访问这些受保护的方法。
您想做的是观察一个实例,看看是否有任何变化。但与此同时,您不希望任何“局外人”改变您正在观察的实例。从某种意义上说,这会产生一个问题,因为您希望有一个对象是可变的,可以更新任何新的状态,而不是可变的,以确保没有人不应该更新这个实例。这两个功能相互冲突,但可以通过创建一个额外的层来解决。
所以您要做的是扩展您的 class、LiveData,使用可以访问其方法的 class。子层,在本例中为 MutableLiveData,能够访问其父层 (/super) 的受保护方法。
现在开始创建实例,并创建 MutableLiveData 的观察者实例。同时,您创建了一个引用同一实例的 LiveData 实例。因为 MutableLiveData 扩展了 LiveData,所以任何 MutableLiveData 实例都是一个 LiveData 对象,因此可以被 LiveData 变量引用。
现在技巧差不多完成了。您只公开 LiveData 实例,没有人可以使用其受保护的方法,也不能将其转换为它的超级(可能在编译时,但不会 运行:运行时错误)。并且您将实际的子 class 实例保密,因此它只能由拥有该实例的人使用实例的方法进行更改。
//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(.....)
现在超级 class 会在应用任何更改时发出通知。
//change the instance by using the sub class
_name.postValue(...)
//or _name.setValue(...)
Blockquote
Generally speaking, is such a form of inheritance (increasing the visibility of certain methods being the only change) a well-known practice and what are some scenarios where it may be useful (assuming we have access to all the code)?
是的,相当well-known,上面描述的是一个常见的场景。移除观察者模式,将其设为 set/get 形式同样会从中受益。取决于你在哪里实施它,最终没有黄金法则。
看起来 MutableLiveData
与 LiveData
的区别仅在于使 setValue()
和 postValue()
方法 public,而在 LiveData
中它们受到保护。
为什么要为此更改单独 class 而不是简单地将这些方法定义为 LiveData
本身中的 public?
一般来说,这种形式的继承(增加某些方法的可见性是唯一的变化)是一种众所周知的做法吗?它在哪些场景中可能有用(假设我们可以访问所有代码)?
在LiveData - Android Developer Documentation中,可以看到对于LiveData
、setValue()
& postValue()
方法不是public.
然而,在MutableLiveData - Android Developer Documentation中,您可以看到,MutableLiveData
在内部扩展了LiveData
,而且LiveData
的两个魔术方法是publicly 可用,它们是 setValue()
& postValue()
.
setValue()
:设置值并将值分发给所有活跃的观察者,必须从主线程.
postValue()
: post 主线程的任务覆盖 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
public.
我能想起的一个用例是在 Kotlin 中使用 Backing Property 进行封装。
您可以将 LiveData
公开给您的 Fragment/Activity(UI 控制器),即使您可以在 ViewModel
class 中使用 MutableLiveData
进行操作。
class TempViewModel : ViewModel() {
...
private val _count = MutableLiveData<Int>()
val count: LiveData<Int>
get() = _count
public fun incrementCount() = _count.value?.plus(1)
...
}
这样您的 UI 控制器将只能观察值而不能编辑它们。显然,您的 UI 控制器可以使用 TempViewModel
的 public 方法编辑值,例如 incrementCount()
.
注:澄清mutable/immutable困惑-
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
}
MutableLiveData 是从 LiveData 扩展而来的。 LiveData 的受保护方法只能由 self 或 subclasses 寻址。因此在这种情况下,作为 LiveData 的子 class 的 MutableLiveData 可以访问这些受保护的方法。
您想做的是观察一个实例,看看是否有任何变化。但与此同时,您不希望任何“局外人”改变您正在观察的实例。从某种意义上说,这会产生一个问题,因为您希望有一个对象是可变的,可以更新任何新的状态,而不是可变的,以确保没有人不应该更新这个实例。这两个功能相互冲突,但可以通过创建一个额外的层来解决。
所以您要做的是扩展您的 class、LiveData,使用可以访问其方法的 class。子层,在本例中为 MutableLiveData,能够访问其父层 (/super) 的受保护方法。
现在开始创建实例,并创建 MutableLiveData 的观察者实例。同时,您创建了一个引用同一实例的 LiveData 实例。因为 MutableLiveData 扩展了 LiveData,所以任何 MutableLiveData 实例都是一个 LiveData 对象,因此可以被 LiveData 变量引用。
现在技巧差不多完成了。您只公开 LiveData 实例,没有人可以使用其受保护的方法,也不能将其转换为它的超级(可能在编译时,但不会 运行:运行时错误)。并且您将实际的子 class 实例保密,因此它只能由拥有该实例的人使用实例的方法进行更改。
//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(.....)
现在超级 class 会在应用任何更改时发出通知。
//change the instance by using the sub class
_name.postValue(...)
//or _name.setValue(...)
Blockquote Generally speaking, is such a form of inheritance (increasing the visibility of certain methods being the only change) a well-known practice and what are some scenarios where it may be useful (assuming we have access to all the code)?
是的,相当well-known,上面描述的是一个常见的场景。移除观察者模式,将其设为 set/get 形式同样会从中受益。取决于你在哪里实施它,最终没有黄金法则。