LiveData 原理

本文深入解析了Android LiveData的内部工作机制,特别是其如何在生命周期变化时调用dispatchingValue方法来更新Observer。当Observer与LifecycleOwner关联并监听生命周期状态时,LiveData会在LifecycleOwner处于活跃状态时触发数据变更通知。在数据更新或生命周期状态改变时,LiveData会检查Observer的活性和版本号,确保只向活跃且未接收到最新数据的Observer发送更新。这一过程涉及到了LiveData的主动更新和生命周期管理,确保了高效的内存使用和用户体验。

生命周期变化时调用 LiveData.dispatchingValue

在调用 observe 时,我们需要传入 LifecycleOwner 和 Observer,在 observe 方法内部通过 LifecycleBoundObserver 将 Observer 和 LifecycleOwner 关联,并监听 LifecycleOwner 状态

public void observe(LifecycleOwner owner, Observer<? super T> observer) {
    assertMainThread("observe");
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    owner.getLifecycle().addObserver(wrapper);
}

LifecycleBoundObserver 实现了 onStateChanged 接口,内部通过 LifecycleOwner 获取当前声明周期,如果是 DESTROYED 状态,则调用 LiveData.removeObserver,否则继续调用 activeStateChanged 方法

void activeStateChanged(boolean newActive) {
    if (newActive == mActive) {
        return;
    }
    // immediately set active state, so we'd never dispatch anything to inactive
    // owner
    mActive = newActive;
    changeActiveCounter(mActive ? 1 : -1);
    if (mActive) {
        dispatchingValue(this);
    }
}

在 activeStateChanged 方法中,如果当前 Lifecycle 是 active 状态,继续调用 dispatchingValue 方法

setData 方法调用 LiveData.dispatchingValue

LiveData 主动更新数据的入口是 setData 方法,首先版本信息加一,然后调用 dispatchingValue 方法:

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

我们继续看 dispatchingValue 的具体实现

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

其实 LiveData 类中只是维护了 mObservers 信息,并提供了一些工具方法,dispatchingValue 最终调用 considerNotify(Observer)

private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

在 considerNotify 中,如果 Observer 的版本号没有变化,则不更新(对应声明周期变化的路径),否则修改 mLastVersion,进而调用 Observer.onChanged 方法

总结:生命周期变化以及调用 setData 时会调用 LiveData.dispatchingValue,遍历 Observer,判断 Observer 的状态以及版本号信息,来判断是否通知数据变化

LiveData是一个可观察的数据持有者类,它能够感知组件(如Activity、Fragment)的生命周期,确保数据仅在组件处于活跃状态时更新UI,避免了内存泄漏和不必要的UI更新。其核心原理主要涉及以下几个方面: ### 核心组件 LiveData的核心组件包括LiveData本身、Observer(观察者)和Lifecycle(生命周期)。LiveData用于存储和管理数据,Observer用于观察LiveData中数据的变化,Lifecycle则用于感知组件的生命周期状态。 ### 生命周期感知 LiveData内部通过Lifecycle来感知组件的生命周期。当一个Observer通过`observe()`方法注册到LiveData上时,LiveData会获取该Observer所关联的LifecycleOwner(如Activity或Fragment),并将自身与LifecycleOwner的生命周期绑定。在组件的生命周期发生变化时,LiveData会根据LifecycleOwner的状态来决定是否通知Observer数据的变化。例如,当组件处于DESTROYED状态时,LiveData会自动移除该Observer,避免内存泄漏[^3]。 ### 数据更新与分发 当LiveData中的数据发生变化时,会调用`setValue()`(在主线程调用)或`postValue()`(在子线程调用)方法来更新数据。`setValue()`方法会直接更新数据并通知所有活跃的Observer;`postValue()`方法会将数据更新操作封装成一个Runnable对象,并将其发送到主线程的消息队列中,待主线程处理该Runnable时再更新数据并通知Observer。 ### 示例代码解释 ```kotlin val result: LiveData<Result> = liveData { // 在协程中执行耗时操作 val data = repository.fetchData() emit(data) // 发射结果 // 还可以发射多个值 try { emit(Result.Loading) val moreData = repository.fetchMoreData() emit(Result.Success(moreData)) } catch (e: Exception) { emit(Result.Error(e)) } } ``` 上述代码使用了LiveData构建器,在协程中执行耗时操作,并通过`emit()`方法发射数据。`emit()`方法实际上是调用了`setValue()`方法来更新LiveData中的数据,并通知活跃的Observer。 ### 多LiveData组合 LiveData还提供了`MediatorLiveData`类,用于组合多个LiveData对象。当其中一个LiveData对象的数据发生变化时,`MediatorLiveData`会将变化通知给它的Observer。例如: ```kotlin val liveData1 = MutableLiveData<String>() val liveData2 = MutableLiveData<String>() val mediatorLiveData = MediatorLiveData<String>() mediatorLiveData.addSource(liveData1) { value -> mediatorLiveData.value = value } mediatorLiveData.addSource(liveData2) { value -> mediatorLiveData.value = value } ``` 在上述代码中,`mediatorLiveData`监听了`liveData1`和`liveData2`的变化,并将变化的值赋给自己。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

little-sparrow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值