前言:在實現(xiàn)這個事件分發(fā)的時候也考慮過EventBus,因為種種原因沒有采用,但是項目有個事件分發(fā)又非常方便,于是乎有了自己寫個Bus的想法,之所以使用RxJava是考慮到RxAndroid簡直不要太好用,各種線程間的切換如絲般順滑,我們做Android開發(fā)的時候切換線程比較麻煩,索性給他改造一下就是個很簡單的事件分發(fā)工具。
首先要知悉,這個工具只是我在做一個項目的時候偶然頭腦發(fā)熱搞出來的小玩意,沒什么技術(shù)含量(連構(gòu)思帶實現(xiàn)一共才用了半天時間),不知道在大型項目上運行會出現(xiàn)什么未知的BUG,分享僅作為個人筆記和經(jīng)驗交流,如對您的項目有幫助,榮幸之至,反之請一笑置之;
特性:
支持同時向多個類發(fā)送數(shù)據(jù),在多個類里定義一樣的tag即可
基于RxJava,所以線程切換于RxJava、RxAndroid一致
除了可以發(fā)送數(shù)據(jù),還可以主動向注冊事件的位置獲取數(shù)據(jù)
代碼少
開始:首先要引入RxJava和RxAndroid(無版本要求)
//RxJava
implementation 'io.reactivex.rxjava2:rxjava:2.2.6'
//RxAndroid
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
然后。。。。。直接去文章末尾復(fù)制代碼吧,200多行代碼
使用方法:
發(fā)送數(shù)據(jù)
1.在基類中根據(jù)生命周期解綁
@Override
protected void onDestroy() {
super.onDestroy();
QxBus.getInstance().unregister(this);
}
2.在任意位置注冊,String可以更換任意指定類型(基礎(chǔ)類型不可以),但對應(yīng)tag的發(fā)送消息也需要是同類型,否則會導(dǎo)致崩潰
QxBus.subscribe(this, tag, new QxBus.BusObserver<String>() {
@Override
public void onNext(@NotNull String s) {
ToastUtils.show(s);
}
});
3.在任意位置發(fā)送消息
QxBus.post(tag, "登錄成功");
獲取數(shù)據(jù)
1.在合適位置訂閱一個獲取數(shù)據(jù)的監(jiān)聽
QxBus.subGet(this, "tag", new QxBus.OnGetDataListener<String>() {
@Override
public String data() {
return "獲取數(shù)據(jù)成功";
}
});
2.在使用數(shù)據(jù)的位置調(diào)用get
QxBus.get("tag", new QxBus.BusObserver<String>() {
@Override
public void onNext(@NotNull String s) {
ToastUtils.show(s);
}
});
所以只要tag保持一致,就可以正常發(fā)送和接收數(shù)據(jù);
不過要時刻注意,因為使用了粗暴的泛型,同名的tag標簽的發(fā)送和接收對象必須是同類型,否則直接崩潰沒商量,tag就是個字符串,多定義一些,防止兩個不同邏輯使用同一個tag就不會出錯
/**
* Author: 蕭清軒
* Date : 2022/10/14
* Dest : 基于RxJava封裝的事件分發(fā)總線
*/
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 對應(yīng)類 unregister(this)
*/
public void unregister(Object obj) {
if (obj == null) return;
String tag = obj.getClass().getName();
map.remove(tag);
}
/**
* 發(fā)送消息
*
* @param subscribeOn 發(fā)送線程
* @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);
}
}
}
/**
* 開放方法 發(fā)送消息
* 簡化{@link #send(Scheduler, Scheduler, String, Object)} 的調(diào)用
* 最常用的方法,向訂閱指定標簽的位置發(fā)送數(shù)據(jù)
*
* @param tag 消息標簽
* @param data 數(shù)據(jù)
* @param <T> 對象類型
*/
public static <T> void post(String tag, T data) {
post(Schedulers.io(), tag, data);
}
/**
* 向主線程發(fā)送消息
*/
public static <T> void post(Scheduler subscribeOn, String tag, T data) {
post(subscribeOn, AndroidSchedulers.mainThread(), tag, data);
}
/**
* 向任意指定線程發(fā)送消息
*
* @param subscribeOn 發(fā)送線程
* @param observeOn 接收線程
*/
public static <T> void post(Scheduler subscribeOn, Scheduler observeOn, String tag, T data) {
getInstance().send(subscribeOn, observeOn, tag, data);
}
/**
* 訂閱一個主動獲取數(shù)據(jù)的方法
* 和post方法剛好相反,這里是提供數(shù)據(jù),如AActivity 跳轉(zhuǎn)到 BActivity,在BActivity 中通過點擊某個按鈕
* 獲取AActivity中的數(shù)據(jù),可以在AActivity中訂閱一個 subscribeGet 方法,
* 通過 OnGetDataListener.data()的返回值提供數(shù)據(jù)
* 對應(yīng)獲取數(shù)據(jù)的方法為 {@link #getData(String, BusObserver)}
*
* @param tag 標簽
* @param listener 監(jiān)聽器
* @param <T> 數(shù)據(jù)類型
*/
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);
}
/**
* 獲取數(shù)據(jù)
* 意在主動獲取數(shù)據(jù)
* 對應(yīng)注冊方法為{@link #subscribeGet(Object, String, OnGetDataListener)}
*
* @param tag 標簽
* @param busObserver 數(shù)據(jù)觀察者
* @param <T> 數(shù)據(jù)類型
*/
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() {
}
}
/**
* 獲取數(shù)據(jù)的接口,意在簡化 {@link ObservableOnSubscribe} 的操作方式
*
* @param <T> 數(shù)據(jù)類型
*/
public static interface OnGetDataListener<T> {
T data();
}
}