EventBus原理
- 订阅逻辑
register注册订阅者
反射遍历订阅者的方法
通过订阅注解从订阅者中获取订阅事件响应方法的信息
向订阅该事件类型的订阅者集合中添加该订阅者
向该订阅者所订阅的事件类型集合中添加该事件类型 - 事件分发逻辑
将事件添加到ThreadLocal中的MessageQueue
根据事件类型获取所有订阅者
事件分发给订阅时指定对应的处理线程
遍历反射调用事件响应响应方法 - 取消订阅逻辑
根据该订阅者获取所有订阅事件类型
遍历根据事件类型将订阅该事件类型的订阅者集合中删除该订阅者
从map中删除该订阅者和它订阅的事件类型集合
动手实现EventBus
只是实现向在主线程处理消息发送的事件。通过Handler来做异步通信的基础组件,分发处理消息。
- 事件分发逻辑
将事件对象包装为message通过handler添加到主线程的MessageQueue
Looper从messageQueue分发事件触发handleMessage方法
在handleMessage()中根据事件类型找到所有订阅该事件类型的订阅信息
遍历反射调用这些响应该事件类型的方法
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基础组件来处理事件
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) {//循环订阅信息
//反射调用订阅的响应函数
item.method.invoke(item.subscriber, msg.obj);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
};
}
/**
* 懒汉double check单例实现
*
* @return
*/
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
/**
* 注册订阅者
*
* @param subscriber
*/
public void register(Object subscriber) {
Method[] declaredMethods = subscriber.getClass().getDeclaredMethods();
//获取订阅者订阅的事件类型集合
List<Object> events = getEventsBySubscriber(subscriber);
//从订阅者的函数中找到处理事件的响应函数
for (Method item : declaredMethods) {
Subscribe annotation = item.getAnnotation(Subscribe.class);
//通过订阅注解来判断是否是用户订阅的响应函数
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;//记录方法对象,加快反射调用方法速率
//获取订阅事件类型的那些订阅信息集合
List<SubscribeInfo> subscribeInfos = getSubscribeInfosByEvent(eventType);
subscribeInfos.add(info);//添加到对该事件的订阅信息集合中
}
}
}
/**
* 通过订阅者获取订阅的事件类型集合
*
* @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);
}
/**
* 发送消息
* @param event
*/
public void post(Object event) {
Message message = handler.obtainMessage();
message.obj = event;
handler.sendMessage(message);
}
/**
* 延迟发送消息
* @param event
* @param delayMillis
*/
public void postDelay(Object event, long delayMillis) {
Message message = handler.obtainMessage();
message.obj = event;
handler.sendMessageDelayed(message, delayMillis);
}
/**
* 订阅信息:记录订阅者的事件响应函数的信息
*/
class SubscribeInfo {
Object subscriber;//订阅者
Object eventType;//事件类型
Method method;//响应函数
}
}
Subscribe.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HSubscribe {
}
使用
....
EventBus.getDefault().register(this);//注册订阅者
....
//订阅事件响应方法
@Subscribe
public void onComputeEvent(PublishFragment.ComputeEvent event) {
tvContent.setText(event.value + "");
}
=============
....
ComputeEvent event = new ComputeEvent();
event.value = value;
EventBus.getDefault().post(event);//发送事件
....
//事件类型定义
public class ComputeEvent {
public int value;
}