Livedata原理

727 阅读9分钟

1. Livedata特性

LiveData 是一种可观察的数据存储器类。并且具有生命周期感知能力,能遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。

1.1 只有当它关联的应用组件处于生命周期活跃状态时,才会通知对应观察者。

1.2 当关联的应用组件的状态变为 DESTROYED 时,便可移除此观察者,避免内存泄露。

1.3 LiveData 仅在数据发生更改时才发送更新,并且仅发送给活跃观察者。

1.4 观察者从非活跃状态更改为活跃状态时也会收到更新。此外,如果观察者第二次从非活跃状态更改为活跃状态,则只有在自上次变为活跃状态以来,值发生了更改时,它才会收到更新,值没有改变,mversion不变,和LifecycleBoundObserver中的lastverion相同,所有不会通知值。

2. 原理介绍

2.1 Livedata.observe方法

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        //如当前LifecycleOwner的状态的是DESTROYED,就不绑定
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //创建一个LifecycleBoundObserver(生命周期限制的观察者)
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //将观察者添加到mObservers map
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //如果已经存在并且观察者对应的LifecycleOwner不是之前绑定的LifecycleOwner报错
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //如果存在直接返回
        if (existing != null) {
            return;
        }
        //将观察者生命周期和LifecycleOwner对应的Lifecycle绑定
        //当LifecycleOwner的生命周期发生变化时,回调LifecycleBoundObserver中的 onStateChanged
        owner.getLifecycle().addObserver(wrapper);
    }
    
  
public fun interface LifecycleEventObserver : LifecycleObserver {
    /**
     * Called when a state transition event happens.
     *
     * @param source The source of the event
     * @param event The event
     */
    public fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event)
}

1,observe方法先判断LifecycleOwner是否已经处于DESTROYED的状态,如果是就不绑定;

2,然后将创建一个LifecycleBoundObserver,并且将observer和LifecycleBoundObserver添加到观察者map中;

3,最后将LifecycleBoundObserver和LifecycleOwner的生命周期绑定。

2.2 LifecycleBoundObserver

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

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

        @Override
        boolean shouldBeActive() {Å
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        // 当LifecycleOwner生命周期发生变化时,调用这个函数 
       @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
           //LifecycleOwner生命周期改变时,如果LifecycleOwner生命周期处于活跃状态,更新数据
            activeStateChanged(shouldBeActive());
        }

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

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

1,当LifecycleOwner的生命周期变化是会调用LifecycleBoundObserver的onStateChanged方法;

2,判断LifecycleOwner如果处于DESTROYED,移除观察者;

3,否则如果当前是活跃状态,就将最新值通知给所有观察者。

2.3 ObserverWrapper

 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;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            
            //有变化,且是活跃状态,更新数据
            if (mActive) {
                dispatchingValue(this);
            }
        }  
    }

2.4 Livedata.dispatchingValue

 void dispatchingValue(@Nullable ObserverWrapper initiator) {
         //如果正在刷新数据,mDispatchInvalidated置为true,表示之前的刷新无效
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            //如果ObserverWrapper不为null,则只刷新传入的ObserverWrapper
            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;
    }

1,如果传入观察者,则只刷新当前观察者,用于LifecycleOwner生命周期改变时,因为所有的观察者都绑定了LifecycleOwner的生命周期,所以这里还是刷新所有观察者;

2,如果没有传入观察者,遍历观察者map,刷新所有观察者,用于Livedata持有数据改变时;

3,如果刷新的时候,此方法被再次调用,会放弃当前刷新,重新再开始下一轮刷新。

2.5 Livedata.considerNotify

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.
        / 如果当前LifecycleOwner的生命周期是非活跃,不回调onChanged
        //并在LifecycleBoundObserver 中记录状态,当生命周期变为活跃,去更新数据
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //如果观察者中的数据版本大于当前版本就return,就是数据要新于观察者的数据版本时才会通知,这个setValue是在Livedata.setValue里面去自加的
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //调用观察者的onChanged
        observer.mObserver.onChanged((T) mData);
    }

LiveData 使用 版本号机制 来保证观察者从非活跃状态恢复时,只在“值发生变化”时才被通知

如果LiveData没有set过,当观察者从非活跃状态变为活跃状态,会收到通知吗 不会收到通知。

在 LiveData 的源码逻辑中,是否发送更新的关键依据是 mVersion(LiveData 的当前版本号)与观察者包装器的 mLastVersion 比较。 表明只有当 LiveData 的 mVersion 大于观察者上次记录的版本时,才会触发通知

当activity从created变到resumed状态,能收到几次livedate通知

1. 从 CREATED → STARTED

  • 在这一步,LifecycleOwner 已进入 active(即至少 STARTED),LiveData 会调用 considerNotify()。

  • 如果 LiveData 当前有值(即曾调用过 setValue()),那么会执行:

    java
    复制编辑
    if (mVersion > mLastVersion) { 
        onChanged(); 
        mLastVersion = mVersion;
    }
    

    这通常意味着收到一次通知。


🔄 2. 从 STARTED → RESUMED

  • 这一步 Lifecycle 从活动状态变为更活跃,但它仍被 isAtLeast(STARTED) 判断为 active。
  • LiveData 并不会再次调用 considerNotify(),也不会重复发送当前值。
    实际上,二次“激活”没有版本更新,因而不会产生新的 onChanged() 通知。

✅ 整体结论

🌟 在典型情况下,从 CREATED 一路到 RESUMED,你的观察者会接收到****一次** 通知(如果 LiveData 有值)。

  • 若 LiveData 未曾设置过值(mVersion == START_VERSION),则整个过程不会收到任何通知。
  • 如果值已设置,则首次进入 active 状态时触发一次通知,后续相同生命周期状态转换不会重复触发。
START_VERSION=-1
public LiveData(T value) {
    mData = value;
    mVersion = START_VERSION + 1;
}

/**
 * Creates a LiveData with no value assigned to it.
 */
public LiveData() {
    mData = NOT_SET;
    mVersion = START_VERSION;
}

2.5 Livedata.setValue

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

setValue也是调用了dispatchingValue方法,传的参数时null,更新所有观察者。

  • 1,在Livedata.observe方法先判断传入的LifecycleOwner是否已经处于DESTROYED的状态,如果是return,不绑定,

  • 2,然后将创建一个LifecycleBoundObserver,将我们传递的observer封装(作为一个变量),它实现了 LifecycleEventObserver接口,将LifecycleBoundObserver和LifecycleOwner的生命周期绑定,就可以监听LifecycleOwner的生命周期变化,

  • 3,最后将observer 为key和LifecycleBoundObserver为value 添加到观察者map中,便于观察者管理;

  • 4,当LifecycleOwner的生命周期变化时 ,在LifecycleBoundObserver的onStateChanged方法中,再次判断LifecycleOwner如果处于DESTROYED,则从map移除观察者,并解除LifecycleBoundObserver和LifecycleOwner的绑定

  • 5,否则判断LifecycleOwner当前活跃状态和上次活跃状态是否相同(把生命周期抽象成活跃和非活跃状态),不相同,并且至少是STARTED状态,就调用dispatchingValue方法进行通知,传的参数是LifecycleBoundObserver,在dispatchingValue方法中会比较livedata当前的mversion和LifecycleBoundObserver的lastversion,大于时,说明值有变化,才调用 从LifecycleBoundObserver中取出observer.onChanged((T) mData)进行通知;

  • 6,setValue设置值前先将mVersion++,然后给mData设置最新值,最后也是调用了dispatchingValue方法,传的参数时null,传null时,就会遍历观察者map,将最新值通知给所有观察者。

后台切前台(同一观察者、数据未变)时,LiveData 不会再通知;而横竖屏重建会产生新观察者,LiveData 会立即把最新值推给它;这两种行为都由同一套规则保证——新活跃观察者必收最新值,同一观察者只有 mVersion > lastVersion时才通知。


  • 后台 → 前台(同一 Fragment/Activity 实例,同一 Observer)

    • mLastVersion == mVersion
    • ✅ 不调用 onChanged(不通知)
  • 横竖屏切换(新 Fragment 实例 → 新 Observer)

    • 新 Observer 的 mLastVersion = -1 < mVersion
    • ✅ 立即通知一次(恢复最新数据)
后台切前台要在 `onCreateView / onCreate`中 observe
override fun onCreateView(...) {
    ...
    viewModel.liveData.observe(viewLifecycleOwner) {
        updateUI(it)
    }
}或者或至少保证 observer 是同一个对象
private val observer = Observer<Int> {
    updateUI(it)
}

override fun onStart() {
    super.onStart()
    liveData.observe(viewLifecycleOwner, observer)
}
才能保证不被重复通知。

同一个 Observer 实例不会被重复加入,所以即使在onstart里面调用livedatda绑定的observer,只要observer不是最新的就忽略。
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null) {
    return; // ✅ 直接忽略
}

public enum State {
    DESTROYED,
    INITIALIZED,
    CREATED,
    STARTED,     // ✅ 活跃
    RESUMED      // ✅ 活跃
}

横竖屏切换
Fragment:
onPause
onStop
onDestroyView   ← View 被销毁
onDestroy       ← Fragment 实例被销毁(如未设 retainInstance)

↓ 新实例创建 ↓

onCreate
onCreateView
onStart        
onResume

后台切前台
onPause
onStop
↓
(回到前台)
onStart
onResume

LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);

LifecycleBoundObserver实现了LifecycleEventObserver,感知lifycleower的生命周期,继承了ObserverWrapper,可以记录observer的数据版本

/**
 * Posts a task to a main thread to set the given value. So if you have a following code
 * executed in the main thread:
 * <pre class="prettyprint">
 * liveData.postValue("a");
 * liveData.setValue("b");
 * </pre>
 * The value "b" would be set at first and later the main thread would override it with
 * the value "a".
 * <p>
 * If you called this method multiple times before a main thread executed a posted task, only
 * the last value would be dispatched.
 *
 * @param value The new value
 */
protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}


@Override
public void run() {
    Object newValue;
    synchronized (mDataLock) {
        newValue = mPendingData;
        mPendingData = NOT_SET;
    }
    setValue((T) newValue);
}

postValue在子线程更新数据,是通过主线程的hander post一个runnable执行的的,多次设置的值,一般情况下只有最后一次会被通知给观察者,因为post的值先设置给一个mPendingData,只有mPendingData没有值时,才post一个runnable,如果有值了,就值改变mPendingData的值,不重新post值,特殊情况是主线程已经消费了这个runnale,mPendingData会重置,下次还是会在发送一个runnable,之所以只发送一次runna ble是因为这个runnable是一个异步消息,会阻塞同步消息,所以不能频繁发,参考juejin.cn/post/737348…

LiveData 可以不用有初始值 StateFlow 必须要有初始值

LiveData 只要绑定 LifecycleOwner,自动感知生命周期,,就能自动在页面活跃时分发数据 StateFlow 需要配合repeatOnLifecycle感知生命周期

StateFlow 支持Flow的各种操作符,数据转换比LiveData强大,功能合并两个StateFlow

StateFlow 和LiveData都是订阅者一订阅就能收到最新值(前提是活跃状态),LiveData对一次性事件支持不好,所以key用SharedFlow来处理一次性事件,避免在横竖屏切换重复弹窗

3. 参考

1,blog.csdn.net/xx326664162…

2,developer.android.com/topic/libra…