EventBus原理
- 訂閱邏輯
register注冊(cè)訂閱者
反射遍歷訂閱者的方法
通過訂閱注解從訂閱者中獲取訂閱事件響應(yīng)方法的信息
向訂閱該事件類型的訂閱者集合中添加該訂閱者
向該訂閱者所訂閱的事件類型集合中添加該事件類型 - 事件分發(fā)邏輯
將事件添加到ThreadLocal中的MessageQueue
根據(jù)事件類型獲取所有訂閱者
事件分發(fā)給訂閱時(shí)指定對(duì)應(yīng)的處理線程
遍歷反射調(diào)用事件響應(yīng)響應(yīng)方法 - 取消訂閱邏輯
根據(jù)該訂閱者獲取所有訂閱事件類型
遍歷根據(jù)事件類型將訂閱該事件類型的訂閱者集合中刪除該訂閱者
從map中刪除該訂閱者和它訂閱的事件類型集合
動(dòng)手實(shí)現(xiàn)EventBus
只是實(shí)現(xiàn)向在主線程處理消息發(fā)送的事件秒旋。通過Handler來做異步通信的基礎(chǔ)組件,分發(fā)處理消息二鳄。
- 事件分發(fā)邏輯
將事件對(duì)象包裝為message通過handler添加到主線程的MessageQueue
Looper從messageQueue分發(fā)事件觸發(fā)handleMessage方法
在handleMessage()中根據(jù)事件類型找到所有訂閱該事件類型的訂閱信息
遍歷反射調(diào)用這些響應(yīng)該事件類型的方法
public class EventBus {
private volatile static EventBus defaultInstance;
private static Map<Object, List<Object>> subscribeEventsMap = new HashMap<>();//訂閱者-事件類型集合
private static Map<Object, List<SubscribeInfo>> eventSubscribesMap = new HashMap<>();//事件類型-訂閱信息集合
private Handler handler;//異步通信組件
private EventBus() {
//初始化handler基礎(chǔ)組件來處理事件
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Class eventType = msg.obj.getClass();
//獲取訂閱該事件類型的訂閱信息集合
List<SubscribeInfo> subscribeInfos = eventSubscribesMap.get(eventType);
if (subscribeInfos == null || subscribeInfos.size() != 0) return;
try {
for (SubscribeInfo item : subscribeInfos) {//循環(huán)訂閱信息
//反射調(diào)用訂閱的響應(yīng)函數(shù)
item.method.invoke(item.subscriber, msg.obj);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
};
}
/**
* 懶漢double check單例實(shí)現(xiàn)
*
* @return
*/
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
/**
* 注冊(cè)訂閱者
*
* @param subscriber
*/
public void register(Object subscriber) {
Method[] declaredMethods = subscriber.getClass().getDeclaredMethods();
//獲取訂閱者訂閱的事件類型集合
List<Object> events = getEventsBySubscriber(subscriber);
//從訂閱者的函數(shù)中找到處理事件的響應(yīng)函數(shù)
for (Method item : declaredMethods) {
Subscribe annotation = item.getAnnotation(Subscribe.class);
//通過訂閱注解來判斷是否是用戶訂閱的響應(yīng)函數(shù)
if (annotation != null) {
Class<?>[] parameterTypes = item.getParameterTypes();
if (parameterTypes.length != 1) {
throw new IllegalArgumentException("subscribe event must have ont event object!");
}
Class eventType = parameterTypes[0];
events.add(eventType);//添加到該訂閱事件集合中
SubscribeInfo info = new SubscribeInfo();
info.subscriber = subscriber;
info.eventType = eventType;
info.method = item;//記錄方法對(duì)象绢片,加快反射調(diào)用方法速率
//獲取訂閱事件類型的那些訂閱信息集合
List<SubscribeInfo> subscribeInfos = getSubscribeInfosByEvent(eventType);
subscribeInfos.add(info);//添加到對(duì)該事件的訂閱信息集合中
}
}
}
/**
* 通過訂閱者獲取訂閱的事件類型集合
*
* @param subscriber
* @return
*/
private List<Object> getEventsBySubscriber(Object subscriber) {
List<Object> events = null;
if (subscribeEventsMap.containsKey(subscriber)) {
events = subscribeEventsMap.get(subscriber);
} else {
events = new ArrayList<>();
subscribeEventsMap.put(subscriber, events);
}
return events;
}
/**
* 通過事件類型獲取所有訂閱它的訂閱信息
*
* @param eventType
* @return
*/
private static List<SubscribeInfo> getSubscribeInfosByEvent(Class eventType) {
List<SubscribeInfo> subscribeInfos = null;
if (eventSubscribesMap.containsKey(eventType)) {
eventSubscribesMap.get(eventType);
} else {
subscribeInfos = new ArrayList<>();
eventSubscribesMap.put(eventType, subscribeInfos);
}
return subscribeInfos;
}
/**
* 取消訂閱者
*
* @param subscriber
*/
public void unregister(Object subscriber) {
Object eventType = subscribeEventsMap.get(subscriber);
if (eventType == null) return;
eventSubscribesMap.remove(eventType);
subscribeEventsMap.remove(subscriber);
}
/**
* 發(fā)送消息
* @param event
*/
public void post(Object event) {
Message message = handler.obtainMessage();
message.obj = event;
handler.sendMessage(message);
}
/**
* 延遲發(fā)送消息
* @param event
* @param delayMillis
*/
public void postDelay(Object event, long delayMillis) {
Message message = handler.obtainMessage();
message.obj = event;
handler.sendMessageDelayed(message, delayMillis);
}
/**
* 訂閱信息:記錄訂閱者的事件響應(yīng)函數(shù)的信息
*/
class SubscribeInfo {
Object subscriber;//訂閱者
Object eventType;//事件類型
Method method;//響應(yīng)函數(shù)
}
}
Subscribe.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HSubscribe {
}
使用
....
EventBus.getDefault().register(this);//注冊(cè)訂閱者
....
//訂閱事件響應(yīng)方法
@Subscribe
public void onComputeEvent(PublishFragment.ComputeEvent event) {
tvContent.setText(event.value + "");
}
=============
....
ComputeEvent event = new ComputeEvent();
event.value = value;
EventBus.getDefault().post(event);//發(fā)送事件
....
//事件類型定義
public class ComputeEvent {
public int value;
}