Android总线之LiveDataBus

LiveDataBus概述

一、定义

LiveDataBus是用LiveData实现的事件总线工具类,用于实现数据传递,实现Android组件之间、组件与后台线程之间通信,可用来替换EventBus。

1.为什么要用LiveData实现事件总线呢

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。 LiveData 具有生命周期感知能力,确保界面符合数据状态,不会发生内存泄露,不会因 Activity停止而导致崩溃,不再需要手动处理生命周期以及手动调用反注册方法,数据始终保持最新状态。

2.LiveDataBus对比EventBus、RxBus优点

LiveDataBus的实现简单,相对EventBus复杂的实现,LiveDataBus只需要一个类就可以实现。 LiveDataBus可以减小APK包的大小,由于LiveDataBus只依赖Android官方Android Architecture Components组件的LiveData,没有其他依赖,本身实现只有一个类。作为比较,EventBus JAR包大小为57kb,RxBus依赖RxJava和RxAndroid,其中RxJava2包大小2.2MB,RxJava1包大小1.1MB,RxAndroid包大小9kb。使用LiveDataBus可以大大减小APK包的大小。 LiveDataBus依赖方支持更好,LiveDataBus只依赖Android官方Android Architecture Components组件的LiveData,相比RxBus依赖的RxJava和RxAndroid,依赖方支持更好。 LiveDataBus具有生命周期感知,在Android系统中使用调用者不需要调用反注册,相比EventBus和RxBus使用更为方便,并且没有内存泄漏风险。

3.LiveDataBus缺点

为了解决下文介绍的出现的粘性问题,有各种反射或者侵入性比较强的解决方式因为LiveData本身是单进程数据,因此不支持跨进程(也可以通过Android的跨进程方式做一个桥接比如通过AIDL实现LiveData的跨进程通信),只支持多线程

二、LiveDataBus实现

主要实现步骤

通过 map 维护一个消息事件和 MutableLiveData 的映射关系,MutableLiveData 的类型默认为 Object,接收任意类型,实现总线通信 将 LiveDataBus 封装为一个单例类 消息注册时,如果当前 map 中不存在,则先将消息和对应的 MutableLiveData 对象放入维护的 map 中,添加映射关系,返回当前 map 中缓存的 MutableLiveData 对象

LiveDataBus简单实现

public final class LiveDataBus {

private final Map> bus;

private LiveDataBus() {

bus = new HashMap<>();

}

private static class SingletonHolder {

private static final LiveDataBus DATA_BUS = new LiveDataBus();

}

public static LiveDataBus get() {

return SingletonHolder.DATA_BUS;

}

public MutableLiveData with(String target, Class type) {

if (!bus.containsKey(target)) {

bus.put(target, new MutableLiveData<>());

}

return (MutableLiveData) bus.get(target);

}

public MutableLiveData with(String target) {

return with(target, Object.class);

}

}

使用问题

在使用这个LiveDataBus的过程中,订阅者会收到订阅之前发布的消息。对于一个消息总线来说,这是不可接受的。无论EventBus或者RxBus,订阅方都不会收到订阅之前发出的消息。对于一个消息总线,LiveDataBus必须要解决这个问题。

核心原因

对于 LiveData,其初始的 version 是-1,当我们调用了其 setValue或者 postValue,其 vesion 会+1;对于每一个观察者的封装 ObserverWrapper,其初始 version 也为-1,也就是说,每一个新注册的观察者,其 version 为-1;当LiveData 设置这个 ObserverWrapper 的时候,如果 LiveData 的 version 大于 ObserverWrapper 的 version,LiveData 就会强制把当前 value 推送给 Observer。

如何解决这个问题呢

只需要在注册一个新的订阅者的时候把 ObserverWrapper 的 version 设置成跟 LiveData 的 version 一致即可。

LiveDataBus最终实现

public final class LiveDataBus {

private final Map> bus;

private LiveDataBus() {

bus = new HashMap<>();

}

private static class SingletonHolder {

private static final LiveDataBus DEFAULT_BUS = new LiveDataBus();

}

public static LiveDataBus get() {

return SingletonHolder.DEFAULT_BUS;

}

public synchronized Observable with(String key, Class type) {

if (!bus.containsKey(key)) {

bus.put(key, new BusMutableLiveData<>(key));

}

return (Observable) bus.get(key);

}

public Observable with(String key) {

return with(key, Object.class);

}

public interface Observable {

// void setValue(T value);

void post(T value);

void postDelay(T value, long delay);

void postDelay(T value, long delay, TimeUnit unit);

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer);

void observeSticky(@NonNull LifecycleOwner owner, @NonNull Observer observer);

void observeForever(@NonNull Observer observer);

void observeStickyForever(@NonNull Observer observer);

void removeObserver(@NonNull Observer observer);

}

private static class BusMutableLiveData extends MutableLiveData implements Observable {

private class PostValueTask implements Runnable {

private Object newValue;

public PostValueTask(@NonNull Object newValue) {

this.newValue = newValue;

}

@Override

public void run() {

setValue((T) newValue);

}

}

@NonNull

private final String key;

private Map observerMap = new HashMap<>();

private Handler mainHandler = new Handler(Looper.getMainLooper());

private BusMutableLiveData(String key) {

this.key = key;

}

public boolean isMainThread() {

return Looper.getMainLooper().getThread() == Thread.currentThread();

}

@Override

public void post(T value) {

if(isMainThread()) setValue(value);

else mainHandler.post(new PostValueTask(value));

}

@Override

public void postDelay(T value, long delay) {

mainHandler.postDelayed(new PostValueTask(value), delay);

}

@Override

public void postDelay(T value, long delay, TimeUnit unit) {

postDelay(value, TimeUnit.MILLISECONDS.convert(delay, unit));

}

@Override

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {

SafeCastObserver safeCastObserver = new SafeCastObserver(observer);

//保存LifecycleOwner的当前状态

Lifecycle lifecycle = owner.getLifecycle();

Lifecycle.State currentState = lifecycle.getCurrentState();

int observerSize = getLifecycleObserverMapSize(lifecycle);

boolean needChangeState = currentState.isAtLeast(Lifecycle.State.STARTED);

if (needChangeState) {

//把LifecycleOwner的状态改为INITIALIZED

setLifecycleState(lifecycle, Lifecycle.State.INITIALIZED);

//set observerSize to -1,否则super.observe(owner, observer)的时候会无限循环

setLifecycleObserverMapSize(lifecycle, -1);

}

super.observe(owner, safeCastObserver);

if (needChangeState) {

//重置LifecycleOwner的状态

setLifecycleState(lifecycle, currentState);

//重置observer size,因为又添加了一个observer,所以数量+1

setLifecycleObserverMapSize(lifecycle, observerSize + 1);

//把Observer置为active

hookObserverActive(safeCastObserver, true);

}

//更改Observer的version

hookObserverVersion(safeCastObserver);

}

public void observeSticky(@NonNull LifecycleOwner owner, @NonNull Observer observer) {

super.observe(owner, new SafeCastObserver<>(observer));

}

@Override

public void observeForever(@NonNull Observer observer) {

if (!observerMap.containsKey(observer)) {

observerMap.put(observer, new ObserverWrapper(observer));

}

super.observeForever(observerMap.get(observer));

}

public void observeStickyForever(@NonNull Observer observer) {

super.observeForever(observer);

}

@Override

public void removeObserver(@NonNull Observer observer) {

Observer realObserver = null;

if (observerMap.containsKey(observer)) {

realObserver = observerMap.remove(observer);

} else {

realObserver = observer;

}

super.removeObserver(realObserver);

if (!hasObservers()) {

LiveDataBus.get().bus.remove(key);

}

}

private void setLifecycleObserverMapSize(Lifecycle lifecycle, int size) {

if (lifecycle == null) {

return;

}

if (!(lifecycle instanceof LifecycleRegistry)) {

return;

}

try {

Field observerMapField = LifecycleRegistry.class.getDeclaredField("mObserverMap");

observerMapField.setAccessible(true);

Object mObserverMap = observerMapField.get(lifecycle);

Class superclass = mObserverMap.getClass().getSuperclass();

Field mSizeField = superclass.getDeclaredField("mSize");

mSizeField.setAccessible(true);

mSizeField.set(mObserverMap, size);

} catch (Exception e) {

e.printStackTrace();

}

}

private int getLifecycleObserverMapSize(Lifecycle lifecycle) {

if (lifecycle == null) {

return 0;

}

if (!(lifecycle instanceof LifecycleRegistry)) {

return 0;

}

try {

Field observerMapField = LifecycleRegistry.class.getDeclaredField("mObserverMap");

observerMapField.setAccessible(true);

Object mObserverMap = observerMapField.get(lifecycle);

Class superclass = mObserverMap.getClass().getSuperclass();

Field mSizeField = superclass.getDeclaredField("mSize");

mSizeField.setAccessible(true);

return (int) mSizeField.get(mObserverMap);

} catch (Exception e) {

e.printStackTrace();

return 0;

}

}

private void setLifecycleState(Lifecycle lifecycle, Lifecycle.State state) {

if (lifecycle == null) {

return;

}

if (!(lifecycle instanceof LifecycleRegistry)) {

return;

}

try {

Field mState = LifecycleRegistry.class.getDeclaredField("mState");

mState.setAccessible(true);

mState.set(lifecycle, state);

} catch (Exception e) {

e.printStackTrace();

}

}

private Object getObserverWrapper(@NonNull Observer observer) throws Exception {

Field fieldObservers = LiveData.class.getDeclaredField("mObservers");

fieldObservers.setAccessible(true);

Object objectObservers = fieldObservers.get(this);

Class classObservers = objectObservers.getClass();

Method methodGet = classObservers.getDeclaredMethod("get", Object.class);

methodGet.setAccessible(true);

Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);

Object objectWrapper = null;

if (objectWrapperEntry instanceof Map.Entry) {

objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();

}

return objectWrapper;

}

private void hookObserverVersion(@NonNull Observer observer) {

try {

//get wrapper's version

Object objectWrapper = getObserverWrapper(observer);

if (objectWrapper == null) {

return;

}

Class classObserverWrapper = objectWrapper.getClass().getSuperclass();

Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");

fieldLastVersion.setAccessible(true);

//get livedata's version

Field fieldVersion = LiveData.class.getDeclaredField("mVersion");

fieldVersion.setAccessible(true);

Object objectVersion = fieldVersion.get(this);

//set wrapper's version

fieldLastVersion.set(objectWrapper, objectVersion);

} catch (Exception e) {

e.printStackTrace();

}

}

private void hookObserverActive(@NonNull Observer observer, boolean active) {

try {

//get wrapper's version

Object objectWrapper = getObserverWrapper(observer);

if (objectWrapper == null) {

return;

}

Class classObserverWrapper = objectWrapper.getClass().getSuperclass();

Field mActive = classObserverWrapper.getDeclaredField("mActive");

mActive.setAccessible(true);

mActive.set(objectWrapper, active);

} catch (Exception e) {

e.printStackTrace();

}

}

}

private static class ObserverWrapper implements Observer {

@NonNull

private final Observer observer;

ObserverWrapper(@NonNull Observer observer) {

this.observer = observer;

}

@Override

public void onChanged(@Nullable T t) {

if (isCallOnObserve()) {

return;

}

try {

observer.onChanged(t);

} catch (ClassCastException e) {

e.printStackTrace();

}

}

private boolean isCallOnObserve() {

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

if (stackTrace != null && stackTrace.length > 0) {

for (StackTraceElement element : stackTrace) {

if ("androidx.lifecycle.LiveData".equals(element.getClassName()) &&

"observeForever".equals(element.getMethodName())) {

return true;

}

}

}

return false;

}

}

private static class SafeCastObserver implements Observer {

@NonNull

private final Observer observer;

SafeCastObserver(@NonNull Observer observer) {

this.observer = observer;

}

@Override

public void onChanged(@Nullable T t) {

try {

observer.onChanged(t);

} catch (ClassCastException e) {

e.printStackTrace();

}

}

}

public static Observable get(@NonNull String key, @NonNull Class type) {

return get().with(key, type);

}

public static Observable get(@NonNull String key) {

return (Observable)get(key, Object.class);

}

public static Observable get(@NonNull Class eventType) {

return get(eventType.getName(), eventType);

}

}

三、使用

上述代码实现了一个通信总线的全部功能,并且还具有生命周期感知功能,使用起来也及其简单,具体使用如下:

注册订阅:

LiveDataBus.get("test", Boolean.class)

.observe(this, new Observer() {

@Override

public void onChanged(Boolean aBoolean) {

}

});

注意:observe仅更新处于活动生命周期状态的应用程序组件观察者,如果需要不受生命周期的影响,只要数据更新就会收到通知可以使用observeForever,这意味着给定的观察者将接收所有事件,并且永远不会被自动删除。需要手动调用removeObserver(Observer)来停止这个LiveData。

发送消息:

LiveDataBus.get("test").post(true);

注意:livedata的setValue只可在主线程下使用,多线程下可使用postValue,当然主线程也可以使用这个。这里实现了自己的post方法,统一判断当前所在线程,调用合适的方式。

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: 

发表评论

返回顶部暗黑模式