LiveData

作者: SunnyDay_ab5f | 来源:发表于2023-05-16 11:41 被阅读0次

    一、LiveData介绍

    LiveData顾名思义就是活着的数据,它是一种可以观察源数据变化的数据存储类。同时具有感知Activity/Fragment生命周期的能力,只在Activity/Fragment活跃状态下更新数据。

    二、LiveData源码解析

    MutableLiveData

    public class MutableLiveData<T> extends LiveData<T> {
    
        /**
         * Creates a MutableLiveData initialized with the given {@code value}.
         *
         * @param value initial value
         */
        public MutableLiveData(T value) {
            super(value);
        }
    
        /**
         * Creates a MutableLiveData with no value assigned to it.
         */
        public MutableLiveData() {
            super();
        }
    
        @Override
        public void postValue(T value) {
            super.postValue(value);
        }
    
        @Override
        public void setValue(T value) {
            super.setValue(value);
        }
    }
    

    MutableLiveData是LiveData的子类,也是我们常用的数据源存储类,这个类代码很简单他重写了父类的postValuesetValue方法,我们看下父类中的实现。

    LiveData

    public abstract class LiveData<T> {
        @SuppressWarnings("WeakerAccess") /* synthetic access */
        final Object mDataLock = new Object();
        static final int START_VERSION = -1;
        @SuppressWarnings("WeakerAccess") /* synthetic access */
        static final Object NOT_SET = new Object();
    
        private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
                new SafeIterableMap<>();
    
        // how many observers are in active state
        @SuppressWarnings("WeakerAccess") /* synthetic access */
        int mActiveCount = 0;
        // to handle active/inactive reentry, we guard with this boolean
        private boolean mChangingActiveState;
        private volatile Object mData;
        // when setData is called, we set the pending data and actual data swap happens on the main
        // thread
        @SuppressWarnings("WeakerAccess") /* synthetic access */
        volatile Object mPendingData = NOT_SET;
        private int mVersion;
    
        private boolean mDispatchingValue;
        @SuppressWarnings("FieldCanBeLocal")
        private boolean mDispatchInvalidated;
        private final Runnable mPostValueRunnable = new Runnable() {
            @SuppressWarnings("unchecked")
            @Override
            public void run() {
                Object newValue;
                synchronized (mDataLock) {
                    newValue = mPendingData;
                    mPendingData = NOT_SET;
                }
                setValue((T) newValue);
            }
        };
    
        /**
         * Creates a LiveData initialized with the given {@code value}.
         *
         * @param value initial value
         */
        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;
        }
    
        @SuppressWarnings("unchecked")
        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);
        }
    
        @SuppressWarnings("WeakerAccess") /* synthetic access */
        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;
        }
    
        /**
         * Adds the given observer to the observers list within the lifespan of the given
         * owner. The events are dispatched on the main thread. If LiveData already has data
         * set, it will be delivered to the observer.
         * <p>
         * The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
         * or {@link Lifecycle.State#RESUMED} state (active).
         * <p>
         * If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
         * automatically be removed.
         * <p>
         * When data changes while the {@code owner} is not active, it will not receive any updates.
         * If it becomes active again, it will receive the last available data automatically.
         * <p>
         * LiveData keeps a strong reference to the observer and the owner as long as the
         * given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
         * the observer &amp; the owner.
         * <p>
         * If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
         * ignores the call.
         * <p>
         * If the given owner, observer tuple is already in the list, the call is ignored.
         * If the observer is already in the list with another owner, LiveData throws an
         * {@link IllegalArgumentException}.
         *
         * @param owner    The LifecycleOwner which controls the observer
         * @param observer The observer that will receive the events
         */
        @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);
        }
    
        /**
         * Adds the given observer to the observers list. This call is similar to
         * {@link LiveData#observe(LifecycleOwner, Observer)} with a LifecycleOwner, which
         * is always active. This means that the given observer will receive all events and will never
         * be automatically removed. You should manually call {@link #removeObserver(Observer)} to stop
         * observing this LiveData.
         * While LiveData has one of such observers, it will be considered
         * as active.
         * <p>
         * If the observer was already added with an owner to this LiveData, LiveData throws an
         * {@link IllegalArgumentException}.
         *
         * @param observer The observer that will receive the events
         */
        @MainThread
        public void observeForever(@NonNull Observer<? super T> observer) {
            assertMainThread("observeForever");
            AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
            ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
            if (existing instanceof LiveData.LifecycleBoundObserver) {
                throw new IllegalArgumentException("Cannot add the same observer"
                        + " with different lifecycles");
            }
            if (existing != null) {
                return;
            }
            wrapper.activeStateChanged(true);
        }
    
        /**
         * Removes the given observer from the observers list.
         *
         * @param observer The Observer to receive events.
         */
        @MainThread
        public void removeObserver(@NonNull final Observer<? super T> observer) {
            assertMainThread("removeObserver");
            ObserverWrapper removed = mObservers.remove(observer);
            if (removed == null) {
                return;
            }
            removed.detachObserver();
            removed.activeStateChanged(false);
        }
    
        /**
         * Removes all observers that are tied to the given {@link LifecycleOwner}.
         *
         * @param owner The {@code LifecycleOwner} scope for the observers to be removed.
         */
        @SuppressWarnings("WeakerAccess")
        @MainThread
        public void removeObservers(@NonNull final LifecycleOwner owner) {
            assertMainThread("removeObservers");
            for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers) {
                if (entry.getValue().isAttachedTo(owner)) {
                    removeObserver(entry.getKey());
                }
            }
        }
    
        /**
         * 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);
        }
    
        /**
         * Sets the value. If there are active observers, the value will be dispatched to them.
         * <p>
         * This method must be called from the main thread. If you need set a value from a background
         * thread, you can use {@link #postValue(Object)}
         *
         * @param value The new value
         */
        @MainThread
        protected void setValue(T value) {
            assertMainThread("setValue");
            mVersion++;
            mData = value;
            dispatchingValue(null);
        }
    
        /**
         * Returns the current value.
         * Note that calling this method on a background thread does not guarantee that the latest
         * value set will be received.
         *
         * @return the current value
         */
        @SuppressWarnings("unchecked")
        @Nullable
        public T getValue() {
            Object data = mData;
            if (data != NOT_SET) {
                return (T) data;
            }
            return null;
        }
    
        int getVersion() {
            return mVersion;
        }
    
        /**
         * Called when the number of active observers change from 0 to 1.
         * <p>
         * This callback can be used to know that this LiveData is being used thus should be kept
         * up to date.
         */
        protected void onActive() {
    
        }
    
        /**
         * Called when the number of active observers change from 1 to 0.
         * <p>
         * This does not mean that there are no observers left, there may still be observers but their
         * lifecycle states aren't {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}
         * (like an Activity in the back stack).
         * <p>
         * You can check if there are observers via {@link #hasObservers()}.
         */
        protected void onInactive() {
    
        }
    
        /**
         * Returns true if this LiveData has observers.
         *
         * @return true if this LiveData has observers
         */
        @SuppressWarnings("WeakerAccess")
        public boolean hasObservers() {
            return mObservers.size() > 0;
        }
    
        /**
         * Returns true if this LiveData has active observers.
         *
         * @return true if this LiveData has active observers
         */
        @SuppressWarnings("WeakerAccess")
        public boolean hasActiveObservers() {
            return mActiveCount > 0;
        }
    
        @MainThread
        void changeActiveCounter(int change) {
            int previousActiveCount = mActiveCount;
            mActiveCount += change;
            if (mChangingActiveState) {
                return;
            }
            mChangingActiveState = true;
            try {
                while (previousActiveCount != mActiveCount) {
                    boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
                    boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
                    previousActiveCount = mActiveCount;
                    if (needToCallActive) {
                        onActive();
                    } else if (needToCallInactive) {
                        onInactive();
                    }
                }
            } finally {
                mChangingActiveState = false;
            }
        }
    
        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);
            }
    
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
                if (currentState == DESTROYED) {
                    removeObserver(mObserver);
                    return;
                }
                Lifecycle.State prevState = null;
                while (prevState != currentState) {
                    prevState = currentState;
                    activeStateChanged(shouldBeActive());
                    currentState = mOwner.getLifecycle().getCurrentState();
                }
            }
    
            @Override
            boolean isAttachedTo(LifecycleOwner owner) {
                return mOwner == owner;
            }
    
            @Override
            void detachObserver() {
                mOwner.getLifecycle().removeObserver(this);
            }
        }
    
        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);
                }
            }
        }
    
        private class AlwaysActiveObserver extends ObserverWrapper {
    
            AlwaysActiveObserver(Observer<? super T> observer) {
                super(observer);
            }
    
            @Override
            boolean shouldBeActive() {
                return true;
            }
        }
    
        static void assertMainThread(String methodName) {
            if (!ArchTaskExecutor.getInstance().isMainThread()) {
                throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                        + " thread");
            }
        }
    }
    
    

    LiveData是一个抽象类,它有一个有参构造函数和一个无参构造函数,看下构造函数中做了哪些处理:

     /**
         * Creates a LiveData initialized with the given {@code value}.
         *
         * @param value initial value
         */
        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;
        }
    
    

    在有参的构造函数中将value赋值给mData并将mVersion+1记录版本号,而无参的构造函数中将Object类型静态全局常量NOT_SET赋值给mData

    下面看下LiveData注册数据变化监听的方法实现:

        @MainThread
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            assertMainThread("observe");
            //如果当前组件的状态等于DESTROYED则不注册返回。
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                // ignore
                return;
            }
            //如果observer不存在则存储在map中
            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 用来获取LifeCycle,一个是Observer对象,用来通知value变化。LifecycleBoundObserver 对参数进行包装,看下LifecycleBoundObserver的代码可以看到它实现了LifecycleEventObserver,所以具有组件生命周期变化感知的能力。当currentState == DESTROYED时自动移除LiveData中map保存的Observer。

     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);
            }
    
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
                //移除Observer
                if (currentState == DESTROYED) {
                    removeObserver(mObserver);
                    return;
                }
                Lifecycle.State prevState = null;
                while (prevState != currentState) {
                    prevState = currentState;
                    activeStateChanged(shouldBeActive());
                    currentState = mOwner.getLifecycle().getCurrentState();
                }
            }
    
            @Override
            boolean isAttachedTo(LifecycleOwner owner) {
                return mOwner == owner;
            }
    
            @Override
            void detachObserver() {
                mOwner.getLifecycle().removeObserver(this);
            }
        }
    

    这里注意下LifecycleBoundObserver父类中的成员变量mLastVersion的值默认就是START_VERSION

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

    下面看下更新value的两个方法setValuepostValue方法,setValue必须在主进程中使用,如果需要在子线程中更新数据则使用postValue方法。

     /**
         * Sets the value. If there are active observers, the value will be dispatched to them.
         * <p>
         * This method must be called from the main thread. If you need set a value from a background
         * thread, you can use {@link #postValue(Object)}
         *
         * @param value The new value
         */
        @MainThread
        protected void setValue(T value) {
            assertMainThread("setValue");
            mVersion++;
            mData = value;
            dispatchingValue(null);
        }
    

    setValue方法中将mVersion++,并将mData更新,然后调用dispatchingValue(null)分发数据。

    @SuppressWarnings("WeakerAccess") /* synthetic access */
        void dispatchingValue(@Nullable ObserverWrapper initiator) {
            //如果正在下发则返回
            if (mDispatchingValue) {
                mDispatchInvalidated = true;
                return;
            }
            mDispatchingValue = true;
            do {
                mDispatchInvalidated = false;
                if (initiator != null) {
                    considerNotify(initiator);
                    initiator = null;
                } else {
                     //遍历map
                    for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                            mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                        considerNotify(iterator.next().getValue());
                        if (mDispatchInvalidated) {
                            break;
                        }
                    }
                }
            } while (mDispatchInvalidated);
            mDispatchingValue = false;
        }
    

    先进行状态检查:观察者是非活跃就return;若当前observer对应的owner非活跃,就会再调用activeStateChanged方法,并传入false,其内部会再次判断。最后回调真正的mObserver的onChanged方法,值是LivaData的变量mData。注意:这里面会判断if (observer.mLastVersion >= mVersion)如果observer的mLastversion大于等于mVersion也返回不处理

    @SuppressWarnings("unchecked")
        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);
        }
    

    postValue实际上是将一个runnable放入主线程中执行

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

    Runnable中实际调用的还是setValue方法。

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

    三、LiveData高级用法

    (1)数据转换 Transformations.map

    MutableLiveData<Integer> liveData = new MutableLiveData<>();
    LiveData<String> stringLiveData = Transformations.map(liveData, new Function<Integer, String>() {
          @Override
          public String apply(Integer input) {
              return Integer.toString(input);
          }
      });
    

    (2) 数据切换 Transformations.switchMap

    //两个liveData,由liveDataSwitch决定 返回哪个livaData数据
            MutableLiveData<String> liveData3 = new MutableLiveData<>();
            MutableLiveData<String> liveData4 = new MutableLiveData<>();
            
     //切换条件LiveData,liveDataSwitch的value 是切换条件
            MutableLiveData<Boolean> liveDataSwitch = new MutableLiveData<>();
            
     //liveDataSwitchMap由switchMap()方法生成,用于添加观察者
            LiveData<String> liveDataSwitchMap = Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() {
                @Override
                public LiveData<String> apply(Boolean input) {
                //这里是具体切换逻辑:根据liveDataSwitch的value返回哪个liveData
                    if (input) {
                        return liveData3;
                    }
                    return liveData4;
                }
            });
    
            liveDataSwitchMap.observe(this, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged2: " + s);
                }
            });
    
            boolean switchValue = true;
            liveDataSwitch.setValue(switchValue);//设置切换条件值
    
            liveData3.setValue("liveData3");
            liveData4.setValue("liveData4");
    

    liveData3、liveData4是两个数据源,有一个判断条件来决定 取哪一个数据 ,这个条件就是liveDataSwitch,如果值为true则取liveData3,false则取liveData4。Transformations.switchMap()就用于实现这一逻辑,返回值liveDataSwitchMap添加观察者就可以了。

    (3)观察多个数据 MediatorLiveData

    MediatorLiveData 是 LiveData 的子类,允许合并多个 LiveData 源。只要任何原始的 LiveData 源对象发生更改,就会触发 MediatorLiveData 对象的观察者

    MediatorLiveData<String> mediatorLiveData = new MediatorLiveData<>();
    
            MutableLiveData<String> liveData5 = new MutableLiveData<>();
            MutableLiveData<String> liveData6 = new MutableLiveData<>();
    
     //添加 源 LiveData
            mediatorLiveData.addSource(liveData5, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged3: " + s);
                    mediatorLiveData.setValue(s);
                }
            });
     //添加 源 LiveData
            mediatorLiveData.addSource(liveData6, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged4: " + s);
                    mediatorLiveData.setValue(s);
                }
            });
    
     //添加观察
            mediatorLiveData.observe(this, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged5: "+s);
                    //无论liveData5、liveData6更新,都可以接收到
                }
            });
            
            liveData5.setValue("liveData5");
            //liveData6.setValue("liveData6");
    

    相关文章

      网友评论

          本文标题:LiveData

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