前言
对于Android系统来说,消息传递是最基本的组件,每一个App内的不同页面,不同组件都在进行消息传递。在这之前,我们会用广播或者eventBus或者Rxbus去做消息的传递,但是现在开始我们可以用LiveDataBus了,相比前面这些消息总线框架,LiveDataBus有如下好处:
1.LiveDataBus可以减小APK包的大小 由于LiveDataBus只依赖Android官方Android Architecture Components组件的LiveData,没有其他依赖,本身实现只有一个类。而Rxbus借助Rxjava,需要引入Rxjava的支持库。
2.LiveDataBus可以感知activity的生命周期,没有内存泄漏的风险。
3.谷歌推荐。
Rxbus
在这里,还是先比较一下Rxbus
public class RxBus {
private static volatile RxBus mDefaultInstance;
private RxBus() {
}
public static RxBus getDefault() {
if (mDefaultInstance == null) {
synchronized (RxBus.class) {
if (mDefaultInstance == null) {
mDefaultInstance = new RxBus();
}
}
}
return mDefaultInstance;
}
private final Subject<Object> _bus = PublishSubject.create().toSerialized();
public void send(Object o) {
_bus.onNext(o);
}
public Observable<Object> toObservable() {
return _bus;
}
/**
* 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者
*
* @param eventType 事件类型
* @param <T>
* @return
*/
public <T> Observable<T> toObservable(Class<T> eventType) {
return _bus.ofType(eventType);
}
/**
* 提供了一个新的事件,根据code进行分发
*
* @param code 事件code
* @param o
*/
public void post(int code, Object o) {
_bus.onNext(new RxBusMessage(code, o));
}
/**
* 根据传递的code和 eventType 类型返回特定类型(eventType)的 被观察者
* 对于注册了code为0,class为voidMessage的观察者,那么就接收不到code为0之外的voidMessage。
*
* @param code 事件code
* @param eventType 事件类型
* @param <T>
* @return
*/
public <T> Observable<T> toObservable(final int code, final Class<T> eventType) {
return _bus.ofType(RxBusMessage.class)
.filter(new Predicate<RxBusMessage>() {
@Override
public boolean test(RxBusMessage rxBusMessage) throws Exception {
//过滤code和eventType都相同的事件
return rxBusMessage.getCode() == code && eventType.isInstance(rxBusMessage.getObject());
}
}).map(new Function<RxBusMessage, Object>() {
@Override
public Object apply(RxBusMessage rxBusMessage) throws Exception {
return rxBusMessage.getObject();
}
}).cast(eventType);
}
/**
* 判断是否有订阅者
*/
public boolean hasObservers() {
return _bus.hasObservers();
}
}
在RxJava中有个Subject类,它继承Observable类,同时实现了Observer接口,因此Subject可以同时担当观察者和被观察者的角色,使用PublishSubject来创建一个Subject对象PublishSubject只有被订阅后才会把接收到的事件立刻发送给观察者。
在需要接收事件的地方,订阅该Subject对象,之后如果Subject对象接收到事件,则会发射给该观察者,此时Subject对象充当被观察者的角色。
完成了订阅,在需要发送事件的地方将事件发送给之前被订阅的Subject对象,则此时Subject对象作为观察者接收事件,然后会立刻将事件转发给订阅该Subject对象的订阅者,以便观察者处理相应事件,到这里就完成了事件的发送与处理。
最后就是取消订阅的操作了,RxJava中,订阅操作会返回一个Disposable对象,调用Disposable.dispose()以便在合适的时机取消订阅,防止内存泄漏。
LiveDataBus
public class LiveDataBusX {
//存放订阅者
private Map<String, BusMutiableLiveData<Object>> bus;
private static LiveDataBusX liveDataBus = new LiveDataBusX();
private LiveDataBusX() {
bus = new HashMap();
}
public static LiveDataBusX getInstance() {
return liveDataBus;
}
//注册订阅者
public synchronized <T> BusMutiableLiveData<T> with(String key, Class<T> type) {
if(!bus.containsKey(key)){
bus.put(key,new BusMutiableLiveData<Object>());
}
return (BusMutiableLiveData<T>)bus.get(key);
}
public static class BusMutiableLiveData<T> extends MutableLiveData{
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
super.observe(owner, observer);
hook(observer);
}
private void hook(Observer<? super T> observer) {
try{
//1.得到mLastVersion
Class<LiveData> liveDataClass=LiveData.class;
Field mObserversFeild=liveDataClass.getDeclaredField("mObservers");
mObserversFeild.setAccessible(true);
//获取到这个成员变量的对象
Object mObserversObject=mObserversFeild.get(this);
//得到map对应的class对象
Class<?> mObserversClass=mObserversObject.getClass();
//需要执行get方法
Method get=mObserversClass.getDeclaredMethod("get",Object.class);
get.setAccessible(true);
Object invokeEntry=get.invoke(mObserversObject,observer);
Object observerWraper=null;
if(invokeEntry!=null && invokeEntry instanceof Map.Entry){
observerWraper=((Map.Entry)invokeEntry).getValue();
}
if(observerWraper==null){
throw new NullPointerException("observerWraper is null!");
}
//得到ObserveWraper的类对象 ,编译擦除问题
Class<?> superclass=observerWraper.getClass().getSuperclass();
Field mLastVersion=superclass.getDeclaredField("mLastVersion");
mLastVersion.setAccessible(true);
//2.得到mVersion
Field mVersion=liveDataClass.getDeclaredField("mVersion");
mVersion.setAccessible(true);
//3.mLastVersion填到mVersion中
Object mVersionValue=mVersion.get(this);
mLastVersion.set(observerWraper,mVersionValue);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
在使用这个LiveDataBus的过程中,订阅者会收到订阅之前发布的消息,这是不可接受的,在LifeData这篇文章中,讲述了原因,思路就是在把observerWraper的mLastVersion设置成个liveData的mVersion一样的值。