前言:在实现这个事件分发的时候也考虑过EventBus,因为种种原因没有采用,但是项目有个事件分发又非常方便,于是乎有了自己写个Bus的想法,之所以使用RxJava是考虑到RxAndroid简直不要太好用,各种线程间的切换如丝般顺滑,我们做Android开发的时候切换线程比较麻烦,索性给他改造一下就是个很简单的事件分发工具。
首先要知悉,这个工具只是我在做一个项目的时候偶然头脑发热搞出来的小玩意,没什么技术含量(连构思带实现一共才用了半天时间),不知道在大型项目上运行会出现什么未知的BUG,分享仅作为个人笔记和经验交流,如对您的项目有帮助,荣幸之至,反之请一笑置之;
特性:
支持同时向多个类发送数据,在多个类里定义一样的tag即可
基于RxJava,所以线程切换于RxJava、RxAndroid一致
除了可以发送数据,还可以主动向注册事件的位置获取数据
代码少
开始:首先要引入RxJava和RxAndroid(无版本要求)
//RxJava
implementation 'io.reactivex.rxjava2:rxjava:2.2.6'
//RxAndroid
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
然后。。。。。直接去文章末尾复制代码吧,200多行代码
使用方法:
发送数据
1.在基类中根据生命周期解绑
@Override
protected void onDestroy() {
super.onDestroy();
QxBus.getInstance().unregister(this);
}
2.在任意位置注册,String可以更换任意指定类型(基础类型不可以),但对应tag的发送消息也需要是同类型,否则会导致崩溃
QxBus.subscribe(this, tag, new QxBus.BusObserver<String>() {
@Override
public void onNext(@NotNull String s) {
ToastUtils.show(s);
}
});
3.在任意位置发送消息
QxBus.post(tag, "登录成功");
获取数据
1.在合适位置订阅一个获取数据的监听
QxBus.subGet(this, "tag", new QxBus.OnGetDataListener<String>() {
@Override
public String data() {
return "获取数据成功";
}
});
2.在使用数据的位置调用get
QxBus.get("tag", new QxBus.BusObserver<String>() {
@Override
public void onNext(@NotNull String s) {
ToastUtils.show(s);
}
});
所以只要tag保持一致,就可以正常发送和接收数据;
不过要时刻注意,因为使用了粗暴的泛型,同名的tag标签的发送和接收对象必须是同类型,否则直接崩溃没商量,tag就是个字符串,多定义一些,防止两个不同逻辑使用同一个tag就不会出错
/**
* Author: 萧清轩
* Date : 2022/10/14
* Dest : 基于RxJava封装的事件分发总线
*/
public class QxBus {
private static volatile QxBus client;
private final Map<String, Map<String, BusObserver<Object>>> map;
private final Map<String, Map<String, OnGetDataListener<Object>>> getMap;
public static QxBus getInstance() {
if (client == null)
synchronized (QxBus.class) {
if (client == null)
client = new QxBus();
}
return client;
}
private QxBus() {
map = new HashMap<>();
getMap = new HashMap<>();
}
/**
* 订阅
*
* @param obj 类
* @param tag 标签
* @param busObserver 观察者
* @param <T> 接收类型
*/
public static <T> void subscribe(Object obj, String tag, BusObserver<T> busObserver) {
getInstance().register(obj, tag, busObserver);
}
public <T> void register(Object obj, String tag, BusObserver<T> busObserver) {
if (obj == null || busObserver == null) return;
String objKey = obj.getClass().getName();
Map<String, BusObserver<Object>> busMap;
if (map.containsKey(objKey)) {
busMap = map.get(objKey);
if (busMap == null) {
busMap = new HashMap<>();
}
} else {
busMap = new HashMap<>();
}
busMap.put(tag, (BusObserver<Object>) busObserver);
map.put(objKey, busMap);
}
/**
* 解绑
* 清除所有 obj类名下的标签,使之失效(伪生命周期)
*
* @param obj 对应类 unregister(this)
*/
public void unregister(Object obj) {
if (obj == null) return;
String tag = obj.getClass().getName();
map.remove(tag);
}
/**
* 发送消息
*
* @param subscribeOn 发送线程
* @param observeOn 目标线程
* @param tag 标记
* @param t 对象
*/
private <T> void send(Scheduler subscribeOn, Scheduler observeOn, String tag, T t) {
for (Map<String, BusObserver<Object>> busMap : map.values()) {
if (busMap != null && busMap.containsKey(tag)) {
BusObserver<T> busObserver = (BusObserver<T>) busMap.get(tag);
if (busObserver != null)
Observable.create((ObservableOnSubscribe<T>) emitter -> {
emitter.onNext(t);
}).subscribeOn(subscribeOn)
.observeOn(observeOn)
.subscribe(busObserver);
}
}
}
/**
* 开放方法 发送消息
* 简化{@link #send(Scheduler, Scheduler, String, Object)} 的调用
* 最常用的方法,向订阅指定标签的位置发送数据
*
* @param tag 消息标签
* @param data 数据
* @param <T> 对象类型
*/
public static <T> void post(String tag, T data) {
post(Schedulers.io(), tag, data);
}
/**
* 向主线程发送消息
*/
public static <T> void post(Scheduler subscribeOn, String tag, T data) {
post(subscribeOn, AndroidSchedulers.mainThread(), tag, data);
}
/**
* 向任意指定线程发送消息
*
* @param subscribeOn 发送线程
* @param observeOn 接收线程
*/
public static <T> void post(Scheduler subscribeOn, Scheduler observeOn, String tag, T data) {
getInstance().send(subscribeOn, observeOn, tag, data);
}
/**
* 订阅一个主动获取数据的方法
* 和post方法刚好相反,这里是提供数据,如AActivity 跳转到 BActivity,在BActivity 中通过点击某个按钮
* 获取AActivity中的数据,可以在AActivity中订阅一个 subscribeGet 方法,
* 通过 OnGetDataListener.data()的返回值提供数据
* 对应获取数据的方法为 {@link #getData(String, BusObserver)}
*
* @param tag 标签
* @param listener 监听器
* @param <T> 数据类型
*/
public <T> void subscribeGet(Object obj, String tag, OnGetDataListener<T> listener) {
if (obj == null || listener == null) return;
String objKey = obj.getClass().getName();
Map<String, OnGetDataListener<Object>> dataMap;
if (getMap.containsKey(objKey)) {
dataMap = getMap.get(objKey);
if (dataMap == null) {
dataMap = new HashMap<>();
}
} else {
dataMap = new HashMap<>();
}
dataMap.put(tag, (OnGetDataListener<Object>) listener);
getMap.put(objKey, dataMap);
}
/**
* {@link #subscribeGet(Object, String, OnGetDataListener)} 的开放方法
*/
public static <T> void subGet(Object obj, String tag, OnGetDataListener<T> listener) {
getInstance().subscribeGet(obj, tag, listener);
}
/**
* 获取数据
* 意在主动获取数据
* 对应注册方法为{@link #subscribeGet(Object, String, OnGetDataListener)}
*
* @param tag 标签
* @param busObserver 数据观察者
* @param <T> 数据类型
*/
public <T> void getData(String tag, BusObserver<T> busObserver) {
if (busObserver == null) return;
Observable.create((ObservableOnSubscribe<T>) emitter -> {
OnGetDataListener<T> listener = null;
for (Map<String, OnGetDataListener<Object>> dataMap : getMap.values()) {
if (dataMap != null && dataMap.containsKey(tag)) {
listener = (OnGetDataListener<T>) dataMap.get(tag);
}
}
if (listener != null) {
emitter.onNext(listener.data());
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(busObserver);
}
/**
* {@link #getData(String, BusObserver)} getData的开放方法
*/
public static <T> void get(String tag, BusObserver<T> busObserver) {
getInstance().getData(tag, busObserver);
}
/**
* 自定义观察者 简化版的{@link Observable}
*/
public abstract static class BusObserver<T> implements Observer<T> {
@Override
public void onSubscribe(@NotNull Disposable d) {
}
@Override
public void onNext(@NotNull T t) {
}
@Override
public void onError(@NotNull Throwable e) {
}
@Override
public void onComplete() {
}
}
/**
* 获取数据的接口,意在简化 {@link ObservableOnSubscribe} 的操作方式
*
* @param <T> 数据类型
*/
public static interface OnGetDataListener<T> {
T data();
}
}