BasicLibrary架构设计旅程(二)—利用LiveData替代EventBus

904 阅读9分钟

背景

  • 去年的时候,我写过一个工具库Rxbus——基于LiveData实现事件消息总线
  • 项目地址:RxBus
  • 美团技术团队之前写过一篇文章: Android消息总线的演进之路:用LiveDataBus替代RxBus、EventBus,对于粘性事件,他们利用的是hook+反射,在性能上反射终究还是会差点。我采用的是新增版本号字段来解决粘性问题
  • 为什么起名RxBus呢?主要我个人比较喜欢这个名字哈,虽然和AndroidKnife大神的RxBus重名了

为什么使用LiveData构建数据通信总线RxBus

LiveData的优势
  • LiveData具有观察和感知生命周期的能力,非常适合作为Android通信总线的基础构件。LiveData只有在活跃状态才会通知数据变化
  • 使用者不需要调用反注册方法。可以完全杜绝其他总线(EventBus、AndroidKnife大神的RxBus)忘记调用反注册所带来的内存泄露的风险
  • UI和实时数据保持一致。因为LiveData使用的是观察者设计模式,数据发生改变时就会获得通知、更新UI
  • 实时数据刷新, 当组件处于活跃状态或者从不活跃状态到活跃状态时总是能收到最新的数据
  • 解决Configuration Change问题, 在屏幕发生旋转或者被回收再次启动,立刻就能收到最新的数据。
为什么使用LiveData替代EventBus
  • 实现简单,一个LiveData实现类即可
  • 减少apk的大小: RxBus只继承了LiveData,没有其他依赖,本身就是一个类。而EventBus的jar包大小为57kb,AndroidKnife大神的RxBus集成了RxAndroid和RxJava,Rxjava2包的大小2.2mb,RxAndroid包大小为9kb。
  • RxBus具有生命周期感知能力,在Android系统中使用调用者不需要调用反注册,相比EventBus和AndroidKnife大神的RxBus使用更方便,也没有内存泄露的风险

从源码的角度带你深入了解liveData

LiveData的简单使用
var github= MutableLiveData<String>()
//setValue
github.value="Github:https://github.com/Peakmain"
//postValue
github.postValue()
//observe
mViewModel.github.observe(this){
    
}
setValue和postValue的区别是什么?

setValue源码

public void setValue(T value) {
    super.setValue(value);
}
@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}
static void assertMainThread(String methodName) {
    if (!ArchTaskExecutor.getInstance().isMainThread()) {
        throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                + " thread");
    }
}

public class ArchTaskExecutor extends TaskExecutor {
    private ArchTaskExecutor() {
        mDefaultTaskExecutor = new DefaultTaskExecutor();
        mDelegate = mDefaultTaskExecutor;
    }
    public boolean isMainThread() {
        return mDelegate.isMainThread();
    }
}
@Override
public boolean isMainThread() {
    return Looper.getMainLooper().getThread() == Thread.currentThread();
}
  • setValue只能运行在主线程中,子线程会直接抛出异常

postValue源码分析

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
  • 这里postToMainThread我就不带大家细看了,主要就是它内部会在DefaultTaskExecutor中创建一个Handler,切换到主线程中执行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);
    }
};
  • 最终还是会执行到setValue,这也就可以看出setValue和postValue的区别是:
    • setValue只能运行在主线程
    • postValue可以运行在子线程
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方法运行在主线程中
  • owner就是我们传的activity/Fragment(关于LiveData中使用Fragment的坑下面会介绍),当我们owner的生命周期是DESTROYED,直接结束
  • 将owner和观察者observer封装到LifecycleBoundObserver,我们继续看下LiecycleBoundObserver是啥
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }
    //代码省略
}
public interface LifecycleEventObserver extends LifecycleObserver {
    void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
  • 我们会发现LifecycleBoundObserver实现了LifecycleEventObserver,而LifecycleEventObserver 继承了LifecycleObserver
  • 大家如果熟悉lifecycle的,立刻应该能反应过来,这其实就是创建了Lifecycle的观察者,随后便是利用addObserve将观察者和被观察者建立关系连接,监听生命周期
  • 关于lifecycle,大家可以看我之前写的文章:jetpack系列——lifecycle源码分析

lifecycle的状态设计模式

lifecycle的状态设计模式.png

Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
  • owner是Activity/fragment
  • currentState==DESTORY,则表示owner的生命周期是onDestory
  • currentState==RESUME则表示owner的生命周期是onResume

LiveData是如何防止内存泄露的

addObserve源码分析

我们回到observe的addObserve源码

@Override
public void addObserver(@NonNull LifecycleObserver observer) {
    enforceMainThreadIfNeeded("addObserver");
    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);
        final Event event = Event.upFrom(statefulObserver.mState);
        if (event == null) {
            throw new IllegalStateException("no event up from " + statefulObserver.mState);
        }
        statefulObserver.dispatchEvent(lifecycleOwner, event);//注释②
        popParentState();
        // mState / subling may have been changed recalculate
        targetState = calculateTargetState(observer);
    }
   //代码省略
}
  • 首先会将owner和INITIALIZED添加到statefulObserver(暂设定在onCreate生命周期),也就是说注释①中statefulObserver.mState等于INITIALIZED
  • observer和statefulObserver添加到mObserverMap,所以注释①中的mObserverMap.contains(observer)一定为true
  • 此时observer是封装后的LifecycleBoundObserver
  • 由于statefulObserver.mState等于INITIALIZED,所以它一定是是小于true,此时会来到注释②

dispatchEvent源码分析

static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;

    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        mState = initialState;
    }

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = event.getTargetState();
        mState = min(mState, newState);
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}
  • 上面addObserve源码分析中我们知道mLifecycleObserver实际是LifecycleBoundObserver,所以会调用LifecycleBoundObserver的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) {
        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();
        }
    }
}
  • 注释①:当owner生命周期是的状态是DESTROYED(也就是onDestory),移除观察观察者

总结: lifecycleBoundObserver中的onStateChange方法中,当当前生命周期是onDestroy的时候,会移除observer

什么是粘性事件?LiveData是如何做到的

什么是粘性事件
  • 上一个页面发送数据A后,下一个页面注册之后还能收到数据A,这种事件就是粘性事件
  • 即粘性事件就是允许先发送数据再注册
如何做到的呢
  • 需求:我们第一个页面setValue,第二个页面observe。分析两个流程源码

回到setValue源码

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}
  • 当LiveData默认无参构造的时候,mVersion=-1,有参构造的时候为0,我们以无参为例,此时mVersion++,就是mVersion=0
  • mData是个Object
  • 看下dispatchingValue源码
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;
}

由于此时没有添加observe所以mObservers为空,所以此时方法直接结束

observe源码

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    //代码省略
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    owner.getLifecycle().addObserver(wrapper);
    //代码省略
}

上面代码我们分析到,实际会调用LifecycleBoundObserver的onStateChanage方法

@Override
public void onStateChanged(@NonNull LifecycleOwner source,
        @NonNull Lifecycle.Event event) {
    Lifecycle.State prevState = null;
    while (prevState != currentState) {
        prevState = currentState;
        activeStateChanged(shouldBeActive());
        currentState = mOwner.getLifecycle().getCurrentState();
    }
}
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);
    }
}

当是活跃状态的时候,会调用dispatchingValue方法

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
          //代码省略
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

会走到considerNotify源码,此时的ObserverWrapper还是LifecycleBoundObserver

private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}
  • 此时肯定是活跃状态,我们上面分析到,此时的mVersion=0
  • observer.mLastVersion默认是-1,也就是说此时observer.mLastVersion >= mVersion一定是false,所以此时就会调用observer的onChanged方法,mData是setData的时候传过去的

总结

  • owner和观察者封装到继承于LifecycleObserver的LifecycleBoundObser
  • 执行addObserver,随后调用观察者ObserverWithState的dispatchEvent
  • 执行LifecycleObserver(LifecycleBoundObser)的onStateChanged(owner)
  • 如果是活跃的状态,会调用dispatchingValue中的considerNotify,再执行onChanage(mData)

RxBus解决LiveData粘性问题

美团技术团队LiveDataBus的原理

美团技术团队采用的hook considerNotify中的

 if (observer.mLastVersion >= mVersion) {
        return;
 }
  • 在observe的时候通过反射将observer.mLastVersion=mVersion
  • 这样当先setValue虽然将mVersion+1了,但是observe调用的时候就将mLastVersion设置成了mVersion的值,调用considerNotify的时候,因为observer.mLastVersion >= mVersion为true直接返回了,也就解决了粘性的问题
我们自己实现的RxBus是怎么实现的呢?

直接贴源码

class RxBus private constructor() {

    companion object {
        private val eventMap = ConcurrentHashMap<String, StickyLiveData<*>>()
        val instance: RxBus by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            RxBus()
        }
    }

    /**
     * register bus
     */
    fun <T> register(eventName: String): StickyLiveData<T> {
        var liveData = eventMap[eventName]
        if (liveData == null) {
            liveData =
                StickyLiveData<T>(
                    eventName
                )
            eventMap[eventName] = liveData
        }
        return liveData as StickyLiveData<T>
    }

    class StickyLiveData<T>(private val eventName: String) : LiveData<T>() {
        internal var mData: T? = null
        internal var mVersion = 0
        private var mSticky: Boolean = false
        fun setData(data: T) {
            setValue(data)
        }

        fun postData(data: T) {
            super.postValue(data)
        }

        /**
         * @param sticky true表示是粘性事件,默认是false
         */
        fun isSticky(sticky: Boolean) {
            mSticky = sticky
        }

        override fun setValue(value: T) {
            ThreadUtils.assertMainThread("StickyLiveData setValue")
            mData = value
            mVersion++
            super.setValue(value)
        }

        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            observerSticky(owner, mSticky, observer)
        }

        private fun observerSticky(
            owner: LifecycleOwner,
            sticky: Boolean,
            observer: Observer<in T>
        ) {
            owner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
                if (event == Lifecycle.Event.ON_DESTROY) {
                    eventMap.remove(eventName)
                }
            })
            super.observe(
                owner,
                StickyObserver(
                    this,
                    sticky,
                    observer
                )
            )
        }
    }

    /**
     * sticky不等于true,只能接收到注册之后发送的消息,如果想接受先发送后注册的消息需要设置sticky为true
     */
    class StickyObserver<T>(
        private val stickyLiveData: StickyLiveData<T>,
        private val sticky: Boolean,
        private val observer: Observer<in T>
    ) : Observer<T> {
        private var lastVersion = stickyLiveData.mVersion
        override fun onChanged(t: T) {
            if (lastVersion >= stickyLiveData.mVersion) {
                if (sticky && stickyLiveData.mData != null) {
                    observer.onChanged(t)
                }
                return
            }
            lastVersion = stickyLiveData.mVersion
            observer.onChanged(t)
        }

    }

}
  • 是不是很惊讶,才100来行代码就实现了一个非粘性的事件分发总线,那怎么实现非粘性的呢
原理

流程:先setValue->observe(粘性)

  • setData,此时RxBus的mVersion+1=1,LiveData的mVersion+1=0
  • observe:此时创建StickyObserver,并设置mLastVersion=mVersion=1
  • 当调用observe的时候会回到considerNotify()方法
private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}
  • 此时LiveData的mLastVersion还是-1,就是会回调mObserver的onChanged方法
  • 此时的mObserver是StickyObserver,也就是调用StickyObserver的onChanged方法
class StickyObserver<T>(
    private val stickyLiveData: StickyLiveData<T>,
    private val sticky: Boolean,
    private val observer: Observer<in T>
) : Observer<T> {
    private var lastVersion = stickyLiveData.mVersion
    override fun onChanged(t: T) {
        if (lastVersion >= stickyLiveData.mVersion) {
            if (sticky && stickyLiveData.mData != null) {
                observer.onChanged(t)
            }
            return
        }
        lastVersion = stickyLiveData.mVersion
        observer.onChanged(t)
    }

}

由于lastVersion>=stickLiveData.mVersion(1=1)成立,所以会默认情况下会直接return(sticky默认false),也就解决了粘性问题

Fragment在LiveData中的使用

  • 上面其实已经是RxBus的所有源码逻辑了,接下来就说一下framgment在LiveData中使用的坑
  • Fragment调用LiveData的observe的时候,owner推荐使用viewLifecycleOwner,而不是this,这是为什么呢
  • 我们上面分析知道,LiveData是监听到生命周期OnDestory的时候,移除观察者,当我们覆盖替换Fragment(replace fragment)的时候,其实并不会调用onDestory,而会调用onDestoryView

Fragment viewLifecycleOwner源码分析

public LifecycleOwner getViewLifecycleOwner() {
    if (mViewLifecycleOwner == null) {
        throw new IllegalStateException("Can't access the Fragment View's LifecycleOwner when "
                + "getView() is null i.e., before onCreateView() or after onDestroyView()");
    }
    return mViewLifecycleOwner;
}

mViewLifecycleOwner创建时机

void performCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
        @Nullable Bundle savedInstanceState) {
  //代码省略
    mViewLifecycleOwner = new FragmentViewLifecycleOwner(this, getViewModelStore());
    mView = onCreateView(inflater, container, savedInstanceState);
   //代码省略
}
  • 我们可以发现mViewLifecycleOwner是在创建mView之前,也就是onCreateView方法之前
  • 我们再来看下Fragment的onDestoryView的时候,mViewLifecycleOwner做了什么
void performDestroyView() {
    mChildFragmentManager.dispatchDestroyView();
    if (mView != null && mViewLifecycleOwner.getLifecycle().getCurrentState()
                    .isAtLeast(Lifecycle.State.CREATED)) {
        mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
    }
    onDestroyView();
    //代码省略
}
  • 此时会执行mViewLifecycleOwner的状态是ON_DESTROY,ON_DESTROY对应的是DESTROYED
  • 我们再回到LiveData的LifecycleBoundObserver的onStateChange
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
       @NonNull Lifecycle.Event event) {
   Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
   if (currentState == DESTROYED) {
       removeObserver(mObserver);
       return;
   }
}
  • 此时的mOwner是mViewLifecycleOwner,因为它此时是DESTROYED,所以会直接移除观察者
总结

image.png

至此本文关于LiveData替代EventBus已经全部介绍完毕,欢迎大家讨论。