LiveData原理

52 阅读5分钟

了解LiveData的内部原理需要关注以下几个问题:

  1. LiveData是如何添加观察者的?
  2. LiveData是如何感知生命周期并仅通知处于Active状态的观察者的?
  3. postValue和setValue的内部实现是什么?
  4. LiveData如何将数据改变通知给观察者( dispatchingValue 方法内部实现)?

1. 添加观察者

示例代码

// observe 方法的第一个参数是 LifecycleOwner,第二个参数是观察者对象
mutableLiveData.observe(this, observer)

源码分析

observe 方法

LiveData 提供了 observe 方法来添加观察者。该方法需要传入两个参数:LifecycleOwnerObserver<T>。以下是 observe 方法的源码解析:

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    // 如果当前状态是 DESTROYED,直接 return
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }
    // 创建 LifecycleBoundObserver 包装类,并将 owner 和 observer 作为参数传入
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    // 将 LiveData 中的观察者 observer 添加到 map 中
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null) {
        return;
    }
    // 将 LifecycleBoundObserver 添加为 Lifecycle 的观察者
    owner.getLifecycle().addObserver(wrapper);
}

observe 方法中:

  1. 创建 LifecycleBoundObserver 包装类,并将 ownerobserver 作为参数传入。
  2. LiveData 中的观察者 observer 添加到 mObservers map 中。
  3. LifecycleBoundObserver 添加为 Lifecycle 的观察者,使得 LiveData 能感知生命周期变化。

2. 感知生命周期

LifecycleBoundObserver

LifecycleBoundObserverLiveData 的静态内部类,继承了 ObserverWrapper 并实现了 LifecycleEventObserver 接口。以下是 LifecycleBoundObserver 的关键实现:

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {

    @NonNull
    final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }

    /**
     * 判断当前状态是否是 Active 的,Active 状态包括 STARTED 和 RESUMED 状态
     */
    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    /**
     * 当生命周期变化时,onStateChanged 方法会被调用
     */
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
        Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
        // 如果当前状态是 DESTROYED,就移除观察者
        if (currentState == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        Lifecycle.State prevState = null;
        while (prevState != currentState) {
            prevState = currentState;
            // 如果活跃状态改变了,就调用 activeStateChanged 方法
            activeStateChanged(shouldBeActive());
            currentState = mOwner.getLifecycle().getCurrentState();
        }
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

LifecycleBoundObserver 中:

  • 实现了 LifecycleEventObserver 接口:当生命周期变化时,onStateChanged 方法会被调用。
  • onStateChanged:根据活跃状态是否改变,调用 activeStateChanged 方法。
  • activeStateChanged:是父类 ObserverWrapper 的方法,根据活跃状态是否是 Active,调用 dispatchingValue 方法。

ObserverWrapper

ObserverWrapper 是观察者的包装类,activeStateChanged 方法在状态变化时调用 dispatchingValue 方法:

private abstract class ObserverWrapper {
    final Observer<? super T> mObserver;
    boolean mActive;
    int mLastVersion = START_VERSION;

    ObserverWrapper(Observer<? super T> observer) {
        mObserver = observer;
    }

    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver() {
    }

    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        mActive = newActive;
        changeActiveCounter(mActive ? 1 : -1);
        if (mActive) {
            dispatchingValue(this);
        }
    }
}

ObserverWrapperactiveStateChanged 方法中,如果状态变为 Active,就调用 LiveDatadispatchingValue 方法,参数为 ObserverWrapper 对象本身。dispatchingValue 方法负责分发数据和通知观察者。

3. postValuesetValue 方法内部实现

LiveData 调用 postValuesetValue 方法后,如果当前页面处于活跃状态,观察者就会收到通知。以下是 postValuesetValue 方法的源码:

protected void postValue(T value) {
    boolean postTask;
    // 使用锁保证多线程中数据的正确性
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    // 将任务调度到主线程执行
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

// postValue 方法将任务调度到主线程后,就会执行 run 方法
private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run() {
        Object newValue;
        // 获取 postValue 设置的 value
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        // 然后调用 setValue 方法
        setValue((T) newValue);
    }
};

@MainThread
protected void setValue(T value) {
    // 如果不是在主线程运行,则抛出 IllegalStateException 异常
    assertMainThread("setValue");
    // mVersion 同 mLastVersion 一起来标记数据是否发生改变
    mVersion++;
    // mData 就是 LiveData 中持有的被观察者数据,每次 setValue 方法被调用都会为其重新赋值
    mData = value;
    // 用于分发数据并通知观察者
    // 在 LifecycleBoundObserver 中,观察到生命周期改变并且是活跃状态,也会调用该方法
    dispatchingValue(null);
}

postValue 将任务切换到主线程,然后调用 setValue 方法。setValue 方法更新数据(为 mData 赋值)并调用 dispatchingValue 方法通知观察者。

4. 分发数据和通知观察者

在分析 LiveData 感知生命周期和 postValue/setValue 方法内部的实现时,我们已经知道最终都会调用 dispatchingValue 来分发数据和通知观察者。

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    // 正在处于分发状态中
    if (mDispatchingValue) {
        // 标记当前分发无效,直接 return
        mDispatchInvalidated = true;
        return;
    }

    // 标记当前处于分发状态
    mDispatchingValue = true;
    do {
        // 分发有效
        mDispatchInvalidated = false;

        // 如果是在 LifecycleBoundObserver 中,观察到生命周期改变并且是活跃状态,调用的本方法,
        // initiator 就是 LifecycleBoundObserver 对象自身,不为 null。
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else { // 如果是 setValue 方法调用的本方法,initiator 为 null
            // 从 map 集合中取出观察者对象的包装类,
            for (Iterator<Map.Entry<Observer<? super T>, LiveData.ObserverWrapper>> iterator =
                 mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                // 通知观察者
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    // 标记不处于分发状态
    mDispatchingValue = false;
}

dispatchingValue 方法主要通过 mDispatchingValue 来标记是否处于分发状态。如果不处于分发状态,则会调用 considerNotify 方法通知观察者。considerNotify 方法源码如下:

private void considerNotify(ObserverWrapper observer) {
    // 如果 ObserverWrapper 的 mActive 值不为 true,就直接 return
    if (!observer.mActive) {
        return;
    }
    // 如果当前 observer 对应组件的状态不是 Active
    if (!observer.shouldBeActive()) {
        // 就会再次调用 activeStateChanged 方法,并传入 false,
        // 其方法内部会再次判断是否执行 onActive 方法和 onInactive 方法回调
        observer.activeStateChanged(false);
        return;
    }
    // mVersion 在何时会变化?
    // postValue/setValue 的时候会改变 mVersion 的值
    // 而只是生命周期状态改变并不会改变 mVersion 的值,所以不会通知观察者
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    // 如果判断条件都满足会调用 Observer 的 onChanged 方法,
    // onChanged 正是使用 LiveData 的 observe 方法的回调
    observer.mObserver.onChanged((T) mData);
}

considerNotify 进行了多次判断,如果是活跃状态才会调用观察者的 onChanged 方法通知观察者。这里需要注意的是 onChanged 方法的参数 mDatamData 是在调用 setValue 方法后立即被赋值的,而 onChanged 方法只有在 Active 状态时才会被调用。因此,当页面处于后台时调用了多次 postValue/setValue 方法,当页面重新回到前台,onChanged 只会调用一次,并且 mData 的值为最后一次 postValue/setValue 的值。

总结

通过上述源码分析,我们了解了 LiveData 的工作原理,包括添加观察者、感知生命周期、postValuesetValue 的内部实现,以及数据分发和通知观察者的机制。LiveData 能够感知组件的生命周期变化并在适当的时机通知观察者,这使得它成为 Android 应用中处理数据和UI更新的一个重要工具。