文章

MVVM数据单向代码写法

下面的代码中count和_doubleCount是否有有点多余,为什么不直接赋值给count和doubleCount?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MainViewModel : ViewModel() {
    private val _count = MutableLiveData<Int>()
    private val _doubleCount = MutableLiveData<Int>()

    val count: LiveData<Int> = _count
    val doubleCount: LiveData<Int> = _doubleCount

    fun incrementCount() {
        _count.value = (_count.value ?: 0).plus(1)
    }

    fun incrementDoubleCount() {
        _doubleCount.value = (_doubleCount.value ?: 0).plus(2)
    }
}

在Android开发里,这种设计模式是相当常见的,主要目的是保证数据的单向流动以及封装性。

下面来详细分析这样设计的原因:

  1. 可变性限制

    • countdoubleCount 属于 LiveData 类型,这意味着它们是不可变的,外部只能对其进行观察,而无法修改。

    • _count_doubleCountMutableLiveData 类型,具有可变性,不过被声明为 private,这样就防止了外部对其进行直接修改。

  2. 数据流向管控
    • 采用这种设计,数据的流动方向就被严格限定为只能从ViewModel到View,也就是单向数据流。
    • 如果外部可以直接对 count 进行修改,那么数据的流向就会变得混乱,ViewModel将难以对数据的状态进行管理。
  3. 安全方面的考量

    • 要是直接把 MutableLiveData 暴露出去,就可能会出现 View 层意外修改数据的情况,这是不符合 MVVM 模式设计理念的。

下面通过一个例子来说明直接暴露 MutableLiveData 可能引发的问题:

1
2
3
4
5
6
7
8
9
10
11
// 错误示范:不要这样做
class MainViewModel : ViewModel() {
    val count = MutableLiveData<Int>() // 直接暴露 MutableLiveData

    fun incrementCount() {
        count.value = (count.value ?: 0).plus(1)
    }
}

// 在Activity中
viewModel.count.value = 100 // 意外地直接修改了LiveData,这违背了数据单向流动原则

总结:这种 private MutableLiveData 搭配 public LiveData 的设计模式,是为了实现数据的单向流动,防止 View 层对数据进行意外修改,从而保证 ViewModel 是唯一能够管理数据状态的地方。

本文由作者按照 CC BY 4.0 进行授权