《第一行代码》第三版p548~549ViewModel数据封装详细解析

3 篇文章 0 订阅
3 篇文章 0 订阅

在第一行代码第三版LiveData最后一块中读到的处理数据封装的方法,之前读过一遍没搞懂,现在思路清晰了,感觉能理解了,以下是个人见解

首先,这段代码

val counter: LiveData<Int>
        get() = _counter

是看懂这一整个代码的第一个关键,书中没有提到kotlin中getter和setter的概念,因为kotlin为变量提供了默认实现,而如果需要覆盖掉原来的getter,那么就需要进行手动实现,也就是在变量下方写上get() = ...,请注意,setter是不能被覆盖的,因为val类型的数据是不能设置的,具体的kotlin语法移步官网

其次因为
MutableLiveData是一个LiveData which publicly exposes setValue(T) and postValue(T) method.(MutableLiveData是一个公开 setValue(T) 和 postValue(T) 方法的LiveData。)
从源码中我们也可以看出

@Override
public void postValue(T value) {
    super.postValue(value);
}
@Override
public void setValue(T value) {
    super.setValue(value);
}

这两个方法的修饰符是public,也就是对外公开。
而LiveData中的方法修饰符是protected,是不能直接调用的

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

而MutableLiveData<Int>又是继承于LiveData<Int>的,所以从LiveData<Int>这个类型get一个MutableLiveData<Int>类型的变量是完全可行的。

所以这样我们给外部提供的是一个LiveData<Int>的子类MutableLiveData<Int>,但是外面外部在调用时,获得的类型实际上是LiveData<Int>,这其实就是一个多态的实现,外部获得的counter只能调用父类LiveData的方法,而不能调用子类MutableLiveData的方法(父类引用指向子类)

从而实现ViewModel的数据封装。

总结一下,一方面归结于val这个不可变变量,没有setter,另一方面就是LiveData<T>这个类中是不能直接调用setValue和postValue这两个方法的。前者是从变量类型阻断修改,后者是从LiveData本身的特性上阻断修改,两者结合,从而保证了ViewModel的数据封装。

改变前的代码:

class MainViewModel(countReserved: Int): ViewModel() {
    val counter = MutableLiveData<Int>()

    init {
        counter.value = countReserved
    }

    fun plusOne(){
        val count = counter.value?:0
        counter.value = count+1;
    }

    fun clear(){
        counter.value = 0
    }
}

改变后的代码

class MainViewModel(countReserved: Int): ViewModel() {
    val counter: LiveData<Int>
        get() = _counter

    private val _counter = MutableLiveData<Int>()

    init {
        _counter.value = countReserved
    }

    fun plusOne(){
        val count = counter.value?:0
        _counter.value = count+1;
    }

    fun clear(){
        _counter.value = 0
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值