Android ABC LiveData的源码分析和去除粘性事件处理(附源码)

写在开头

本文简单介绍了LiveData的源码,并实现了一个非粘性事件添加的类

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

LiveData构造时初始化了一个变量mVersion,数据分发时会根据Version来判断是否要分发

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

包装LifeCycleBoundObserver然后调用LifeCycle进行添加

@Override
public void addObserver(@NonNull LifecycleObserver observer) {
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
    ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

    if (previous != null) {
        return;
    }
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    if (lifecycleOwner == null) {
        // it is null we should be destroyed. Fallback quickly
        return;
    }

    boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
    State targetState = calculateTargetState(observer);
    mAddingObserverCounter++;
    while ((statefulObserver.mState.compareTo(targetState) < 0
            && mObserverMap.contains(observer))) {
        pushParentState(statefulObserver.mState);
        statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
        popParentState();
        // mState / subling may have been changed recalculate
        targetState = calculateTargetState(observer);
    }

    if (!isReentrance) {
        // we do sync only on the top level.
        sync();
    }
    mAddingObserverCounter--;
}

通过while分发事件,这里得出一个结论,LiveData是默认粘性事件处理的,我们有时候不需要粘性事件,怎么办?下面的LiveDataBus提供了解决方案。

为什么一定是粘性事件?

因为一开始创建的observer会被包装成LifecycleBoundObserver,这里面的默认的Version是-1只有调用过onChange之后才会被赋值为最新Version,这个包装方法Google并没有提供给开发者,所以只能自己创建mVersion来管理

回到LiveData的LifecycleBoundObserver,上面statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));最终会调用observer的onStateChanged方法。

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

实现了LifecycleEventObserver,当宿主生命周期改版时就会调用onStateChaged,然后宿主DESTORY之后就移除宿主的Observer

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

否则就进入这个方法,第二个判断是第一次添加observer时的调用,第三个判断是最后一个observer被移除时调用。否则调用dispatchingValue,然后在dispatchingValue中调用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;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

第二个判断判断宿主生命周期是否是start之后,然后判断Version是不是已经跟新过了,否则就调用更新分发

  1. observerForever方法是不会自动帮忙移除Observer的需要手动调用

  2. postValue方法是在子线程中调用设置value时必须使用

    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    
  3. serValue是主线程中调用使用,

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

LiveData实现LiveDataBus

class LiveDataBus {
    private object Lazy {
        var sLiveDataBus = LiveDataBus()
    }

    private val mStickyHashMap = ConcurrentHashMap<String, StickyLiveData<*>>()

    fun <T> with(eventName: String): StickyLiveData<T> {
        var liveData = mStickyHashMap[eventName]
        if (liveData == null) {
            liveData = StickyLiveData<T>(eventName)
            mStickyHashMap[eventName] = liveData
        }
        return liveData as StickyLiveData<T>

    }

    inner class StickyLiveData<T>(private val mEventName: String) : LiveData<T>() {
        private var mStickyData: T? = null
        private var mVersion = 0
        public override fun postValue(value: T?) {
            mVersion++
            super.postValue(value)
        }

        public override fun setValue(value: T?) {
            mVersion++
            super.setValue(value)
        }

        fun setStickyData(data: T?) {
            mStickyData = data
            value = mStickyData!!
        }

        fun postStickyData(mStickyData: T?) {
            this.mStickyData = mStickyData
            postValue(mStickyData)
        }

        override fun observe(owner: LifecycleOwner, observer: Observer<in T?>) {
            observeSticky(owner, observer, false)
        }

        private fun observeSticky(owner: LifecycleOwner, observer: Observer<in T?>, isSticky: Boolean) {
            super.observe(owner, WrapperObserver(this, observer, isSticky))
            owner.lifecycle.addObserver(LifecycleEventObserver { source, event ->
                if (event == Lifecycle.Event.ON_DESTROY) {
                    mStickyHashMap.remove(mEventName)
                }
            })
        }

        private inner class WrapperObserver<T>(val mLiveData: StickyLiveData<T>, val mObserver: Observer<in T?>, val mIsSticky: Boolean) : Observer<T> {
            private var mLastVersion = mLiveData.mVersion
            override fun onChanged(t: T?) {
                if (mLastVersion >= mLiveData.mVersion) {
                    if (mIsSticky && mLiveData.mStickyData != null) {
                        mObserver.onChanged(mLiveData.mStickyData)
                    }
                    return
                }
                mLastVersion = mLiveData.mVersion
                mObserver.onChanged(t)
            }
        }
    }

    companion object {
        fun get(): LiveDataBus {
            return Lazy.sLiveDataBus
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值