Android LiveData笔记

2022-03-03  本文已影响0人  东土也

jetpack中的liveData是一个传递消息的组件。
本节主要是源码分析,使用案例在下一节
主要方法有

//postValue可以在子线程发送数据,也可以在主线程发送数据
public void postValue(T value)
//setValue只可以在主线程发送数据
public void setValue(T value)
//添加观察者,并且不受宿主生命周期影响,永远都会收到消息,需要自己手动控制
public void observeForever(@NonNull Observer<? super T> observer)
//添加观察者受宿主生命周期影响,只有在活动的宿主状态下才能收到消息,在宿主销毁时会移除
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
//当活动观察者的数量从 0 变为 1 时调用。
protected void onActive()
//当活动观察者的数量从 1 变为 0 时调用。
protected void onInactive()

两种方式发送的数据最后都会在主线程上被接收到
主要的类有MutableLiveData,该类知识将LiveData的 postValue和setValue方法由protected改为public,主要是为了实现单一开闭原则
MediatorLiveData是可以接受多个LiveData并将发送事件统一处理

public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction)

该方法是为了将liveData发送的数据转换成另外一种类型的数据
LiveData 的

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

方法会将观察者和宿主的生命周期绑定,内部使用Lifecycl来管理观察者的活跃状态和不活跃状态,
活跃状态会接受消息
不活跃状态不会接受消息
由不活跃状态变为活跃状态则会接受最后一次消息的内容
下面是LiveData的源码分析

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

在你添加观察者时,首先会判断你是否在主线程上操作,不是则报出异常,
接着会判断宿主的生命状态,如果说是在DESTROY则不会添加观察者,随后将观察者包装成LifecycleBoundObserver,并且将包装后的观察者放入列表中。最后一行代码,是将观察者包装对象放入Lifecycle中,让其跟随宿主生命周期变化。

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

在observe()中将观察者包装成LifecycleBoundObserver并监听宿主生命周期,第一次注册进来,onStateChanged()方法将会被调用,在onStateChanged方法中,如果宿主的生命周期状态为DESTROY则会移除观察者,否则将会进入while循环,while循环中通过shouldBeActive()方法判断当前宿主的状态,从而决定观察者是否需要进入活跃状态,之后通过

//该方法中的在分发消息中不会被调用,只有在第一次注册观察者或者宿主生命周期变话的时候才会被调用,所以不用担心if (newActive == mActive)会在分发消息的时候成立。有点绕。
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);
            }
        }

方法开始分发消息,activeStateChanged如果传来newActivity为false,表示当前宿主为非活跃状态,观察者初始状态mActive为false,会进入if语句。
如果newActivity为true说明当前注册观察者的宿主状态为活跃,进入changeActiveCounter方法
最后在判断一次观察者是否处于活跃状态,开始调用dispatchingValue(this);方法进行分发消息

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

changeActiveCounter方法主要是为了检测当前观察者是否有观察者处于活跃状态,或者所有观察者都不处于活跃状态,调用onActive();或者onInactive();两个空方法。

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

由于在public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)方法中传入的initiator不为空,所以上面的方法会直接调用considerNotify(initiator);方法

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

在considerNotify方法中先判断观察者是否处于活跃状态,接着在判断宿主是否处于活跃状态,若宿主处于非活跃状态,则调用activeStateChanged()将观察者改为非活跃状态,最后判断当前分发的消息版本是否和观察者中的消息版本相同,避免重复发送消息,最后调用观察者的onChange方法,分发完成。
至此注册观察者并分发给观察者最后一次消息流程结束
注意观察者注册后会收到最后一次发送的消息

下面是setValue()分发消息

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

setValue方法首先会校验是否在主线程上,接着将消息版本号+1, 然后开始调用dispatchingValue(null);分发消息,由于这次传入的参数为空,所以会进入for循环,遍历所有观察者。流程和上面相似

protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

postValue则是使用handler将线程切换到主线程上,最终还是调用setValue()

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

observeForever方法在最后将观察者状态永远至为true活跃状态,所以可以一直接受信息

上一篇 下一篇

猜你喜欢

热点阅读