美文网首页
LiveData详解

LiveData详解

作者: 饮料只喝芬达 | 来源:发表于2021-06-07 16:20 被阅读0次

    LiveData原理解析

    LiveData是一个数据持有者类,可以在给定的生命周期中观察到。

    observe观察数据变化

        @MainThread
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            assertMainThread("observe");
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                // 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;
            }
            owner.getLifecycle().addObserver(wrapper);
        }
    

    observe被要求在主线程调用,并且传递生命周期相关的LifecycleOwner,

    • 检查观察者生命周期状态
    • 组合LifecycleOwner与observer生成LifecycleBoundObserver并以observer为key存起来
    • 限制观察者只能与一个生命周期绑定并且控制不要重复观察
    • 由于Lifecycle.addObserver会回调当前生命周期,所以observe时会收到一次数据变化
    • LifecycleBoundObserver在生命周期销毁时会移除对LiveData的观察,不需要调用者关心解绑时机
    • 数据变化时通过判断Observer的生命周期状态+当前数据版本号判断是否回调数据变化
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }
    
    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;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }
    

    observeForever观察数据变化

    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        wrapper.activeStateChanged(true);
    }
    

    与observe相似,区别在于

    • observeForever不与生命周期绑定。

    • 记录的观察者为AlwaysActiveObserver

    • 数据变化时判断的Observer的生命周期方法变为不关心生命周期,变化了就回调

      boolean shouldBeActive() {
          return true;
      }
      
    • 不会自动解除绑定,需要主动解除绑定

    ObserverWrapper观察者对象

    ObserverWrapper是LiveData缓存的观察者对象,它是LifecycleBoundObserver与AlwaysActiveObserver的父类

    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;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }
    
    class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @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);
        }
    
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }
    
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
    
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }
    
    private class AlwaysActiveObserver extends ObserverWrapper {
    
        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }
    
        @Override
        boolean shouldBeActive() {
            return true;
        }
    }
    
    private static void assertMainThread(String methodName) {
        if (!ArchTaskExecutor.getInstance().isMainThread()) {
            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread");
        }
    }
    
    • Lifecycle转化到观察者对象里来讲就是一个mActive(是否活跃)状态,如果活跃,则数据变化我就回调mObserver的onChanged方法,如果不活跃则等你重新活跃了再回调给你数据变更。
    • shouldBeActive() 观察者是否活跃
    • isAttachedTo(LifecycleOwner owner) 判断是否已经设置过监听
    • detachObserver() 观察者被移除时回调 LifecycleBoundObserver在detachObserver时会移除对lifecycle的监听
    • activeStateChanged(boolean newActive) 活跃状态变更时回调

    setValue

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

    更新LiveData数据,被要求在主线程调用,调用后数据及数据版本会变化,随后通知观察者

    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;
    }
    

    该方法也做了并发兼容,并支持回调指定的ObserverWrapper,用于在ObserverWrapper从非活跃变成活跃状态并且数据版本发生变化时回调自身。

    postValue

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

    postValue也是更新LiveData数据,只是该方法支持在子线程调用,调用后通过往主线程Handle抛mPostValueRunnable调用setValue实现数据更新

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

    若产生并发则通过替换mPendingData的值来更新数据,而不会重复往主线程抛setValue方法。

    LiveData的缺点

    LiveData的特性是观察者只关心数据变化的最终值,如果你不太关心数据变化的中间值,只要数据变化了能通知到你最新的值的话LiveData已经够用了,甚至项目中它已经可以取代事件总线的地位。
    但如果你需要数据的每一次变化都通知到你的话,就不要用LiveData了。以下场景存在数据丢失的问题

    • postValue高并发情况下只会修改mPendingData值,而不会每次都调用setValue
    • observe更是存在该问题,非活跃状态变成活跃状态时只会收到当前最新值的一次变更通知

    只有observeForever+setValue没有这种问题,条件有些苛刻,不了解原理的话容易踩坑。

    相关文章

      网友评论

          本文标题:LiveData详解

          本文链接:https://www.haomeiwen.com/subject/fsnwsltx.html