LiveData核心原理

本文详细剖析了LiveData的核心原理,讲解了如何通过观察者感知Activity/Fragment生命周期,以及LiveData如何在页面活跃时仅回调观察者。重点介绍了setValue与postValue的区别,以及观察者在不同状态下的行为。

理解《LifeCycle核心原理》的分析,LiveData的分析会比较快速一点。

1)基本使用

xxxViewModel.xxxLiveData.observe(this, (this, new Observer<String>() {
    @Override
    public void onChanged(@Nullable String s) {
         // 业务逻辑
    }
});

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)

其中,第一个参数是被观察者,比如Activity/Fragment;第二个参数是观察者,自定义实现即可。

2)原理分析

  • LiveData为何可以感知生命周期?
  • LiveData如何做到仅在页面Active的情况下,进行回调的?
  • LiveData的setValue与postValue,及其区别

2.1、LiveData为何可以感知生命周期?

首先,需要看一下LiveData的observe方法的源码:

- LiveData
 
   @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {// LiveData已经为我们规避了该状态
            // ignore
            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;
        }
       // #1 核心代码
        owner.getLifecycle().addObserver(wrapper);
    }

先不用看其他部分的代码,仅看一下#1出的核心代码。

结论:LiveData依托于被观察者(Activity/Fragment),向其注册观察者实现生命周期感知。

LiveData向LifecycleOwner(Activity/Fragment)的LifecycleRegistry对象添加了观察者。通过这个观察者,就可以持续收到页面生命周期的变化【触发观察者的onStateChanged方法的调用】。NOTE:Jetpack为我们提供的观察者均实现了LifecycleEventObserver接口,该接口包含了onStateChanged方法,所以对于不同的观察者,其onStateChanged方法的实现是不一样的,可查看ReflectiveGenericLifecycleObserver(通过注解感知生命周期)与LifecycleBoundObserver(LiveData自定义Observer)关于onStateChanged的实现。

  • ReflectiveGenericLifecycleObserver(通过注解感知生命周期) - 反射调用注解方法
  • LifecycleBoundObserver(LiveData自定义Observer) - 触发postValue/setValue方法调用

这里LiveData的做法,与我们在《LifeCycle核心原理》中的示例做法是一致的,所以想要感知生命周期,向页面的LifecycleRegistry对象添加了观察者即可。

可以感知生命周期的原理,可查看《LifeCycle核心原理》的分析。

2)LiveData如何做到仅在页面Active的情况下,进行回调的?

这里我们直接查看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() {// 至少大于STARTED,也就是RESUMED状态
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {// 页面销毁的时候,LiveData主动移除观察者
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());// 在页面是active的前提下,触发postValue/setValue的调用
        }

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

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

3)LiveData的setValue/postValue调用

- LifecycleBoundObserver的父类:ObserverWrapper

  void activeStateChanged(boolean newActive) {
      if (newActive == mActive) {
          return;
      }
      ......
      if (mActive) {
          dispatchingValue(this);// 触发LiveData的dispatchingValue方法调用
       }
  }

- LiveData

    void dispatchingValue(@Nullable ObserverWrapper initiator) {
       ......
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {// onStateChanged的时候走这里
                considerNotify(initiator);
                initiator = null;
            } else {// setValue的时候,走这里
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {// mObservers是LiveData的所有观察者
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

无论走哪一个分支,最终都调用了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.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        // mVersion++;时机是setvalue
        // mVersion的作用是在页面InActive的场景下,比如单独线程每个1秒发送一次请求,那么当页面Active的时候,仅响应最后一个请求【因为响应完,observer.mLastVersion = mVersion;了】
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);// 观察者回调
    }

附:

- LiveData

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


    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

其中,mPostValueRunnable如下:

    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };

可以看到postValue最终也是切换到主线程,调用了setValue方法。

    @Override
    public void postToMainThread(Runnable runnable) {
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    mMainHandler = new Handler(Looper.getMainLooper());
                }
            }
        }
        //noinspection ConstantConditions
        mMainHandler.post(runnable);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值