定义
- EventBus是一款Android下的发布/订阅事件总线机制。可以代替Intent、Handler、Broadcast等在Fragment、Activity之间传递消息。
优点:开销小,代码优雅。将发送者和接受者解耦。
在EventBus中,最重要的是三个map集合:
//Class<?>:响应事件方法参数的类型, Subscription:订阅对象subscriber+SubscriberMethod
private final Map<Class<?>,CopyOnWriteArrayList<Subscription>> subscriptionByEventType;
//Object:订阅对象,List<Class<?>>:方法参数的类型,
private final Map<Object,List<Class<?>>> typesSubscriber;
//黏性事件
private final Map<Class<?>, Object> stickyEvents;
这里主要画图分析第一个集合,也是最重要的一个,该集合主要用于事件分发,如图所示:
其余的两个集合分别用于解除绑定和黏性事件,这里就不再画图分析了,下面我们开始撸代码
核心代码
public class EventBus {
static volatile EventBus defaultInstance;
//Class<?>:响应事件方法参数的类型, Subscription:订阅对象subscriber+SubscriberMethod
private final Map<Class<?>,CopyOnWriteArrayList<Subscription>> subscriptionByEventType;
//Object:订阅对象,List<Class<?>>:方法参数的类型,
private final Map<Object,List<Class<?>>> typesSubscriber;
//黏性事件
private final Map<Class<?>, Object> stickyEvents;
private EventBus(){
subscriptionByEventType = new HashMap<>();
typesSubscriber = new HashMap<>();
stickyEvents = new HashMap<>();
}
/**
* 单例不解释
* @return
*/
public static EventBus getDefault(){
if (defaultInstance == null){
synchronized (EventBus.class){
if (defaultInstance == null){
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
/**
* 注册订阅者
* @param object
*/
public void register(Object object){
//1.解析object中的所有方法,通过Subscribe注解找到响应事件的方法,封装成SubscriberMethod的集合
List<SubscriberMethod> subscriberMethods = new ArrayList<>();
Class<?> clazz = object.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
Subscribe subscribe = method.getAnnotation(Subscribe.class);
if (subscribe != null){
//获取参数类型
Class<?>[] parameterTypes = method.getParameterTypes();
/**
* method:响应事件的方法
* parameterTypes[0] 该方法的参数,注意这里只能有一个参数
* threadMode:线程
* priority:优先级
* sticky:黏性事件
*/
SubscriberMethod subscriberMethod = new SubscriberMethod(method,parameterTypes[0],
subscribe.threadMode(),subscribe.priority(),subscribe.sticky());
subscriberMethods.add(subscriberMethod);
}
}
//2.按照规则存放进subscriptionByEventType
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(object,subscriberMethod);
}
}
private void subscribe(Object object, SubscriberMethod subscriberMethod) {
//方法参数的类型
Class<?> eventType = subscriberMethod.eventType;
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionByEventType.get(eventType);
if (subscriptions == null){
subscriptions = new CopyOnWriteArrayList<>();
subscriptionByEventType.put(eventType,subscriptions);
}
//判断优先级添加
Subscription subscription = new Subscription(object, subscriberMethod);
// 处理优先级
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, subscription);
break;
}
}
//处理粘性事件
if (subscriberMethod.sticky) {
Object stickyEvent = stickyEvents.get(eventType);
if (stickyEvent !=null){
executeMethod(subscription,stickyEvent);
}
}
//用于注销
List<Class<?>> eventTypes = typesSubscriber.get(object);
if (eventTypes == null){
eventTypes = new ArrayList<>();
typesSubscriber.put(object,eventTypes);
}
if (!eventTypes.contains(eventType)){
eventTypes.add(eventType);
}
}
/**
* 解除订阅者,防止内存泄漏
* @param object
*/
public void unregister(Object object){
List<Class<?>> eventTypes = typesSubscriber.get(object);
if (eventTypes != null){
for (Class<?> eventType : eventTypes) {
removeObject(eventType,object);
}
}
}
/**
* 移除订阅者
* @param eventType
* @param object
*/
private void removeObject(Class<?> eventType, Object object) {
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionByEventType.get(eventType);
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == object){
subscriptions.remove(subscription);
i--;
size--;
}
}
}
/**
*事件分发
* @param event
*/
public void post(Object event){
Class<?> eventType = event.getClass();
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionByEventType.get(eventType);
if (subscriptions != null){
for (Subscription subscription : subscriptions) {
executeMethod(subscription,event);
}
}
}
/**
* 在不同线程执行事件
* @param subscription
* @param event
*/
private void executeMethod(final Subscription subscription, final Object event) {
ThreadMode threadMode = subscription.subscriberMethod.threadMode;
boolean isMainThread = Looper.getMainLooper() == Looper.myLooper();
switch (threadMode){
//post的线程
case POSTING:
invokeMethod(subscription,event);
break;
//主线程
case MAIN:
if (isMainThread){
invokeMethod(subscription,event);
}else {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
invokeMethod(subscription,event);
}
});
}
break;
//异步线程
case ASYNC:
AsyncPoster.enqueue(subscription,event);
break;
//后台线程(非主线程)
case BACKGROUND:
if (!isMainThread){
invokeMethod(subscription,event);
}else {
AsyncPoster.enqueue(subscription,event);
}
break;
}
}
/**
* 通过反射执行方法
* @param subscription
* @param event
*/
private void invokeMethod(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber,event);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 发送黏性事件
* @param event 订阅对象
*/
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
post(event);
}
/**
* 移除粘性事件
* @param event
* @return
*/
public boolean removeStickyEvent(Object event) {
synchronized (stickyEvents) {
Class<?> eventType = event.getClass();
Object existingEvent = stickyEvents.get(eventType);
if (event.equals(existingEvent)) {
stickyEvents.remove(eventType);
return true;
} else {
return false;
}
}
}
/**
* 移除全部粘性事件
*/
public void removeAllStickyEvents() {
synchronized (stickyEvents) {
stickyEvents.clear();
}
}
/**
* 获取粘性事件
*/
public <T> T getStickyEvent(Class<T> eventType) {
synchronized (stickyEvents) {
return eventType.cast(stickyEvents.get(eventType));
}
}
/**
* 移除粘性事件
* @param
* @return
*/
public <T> T removeStickyEvent(Class<T> eventType) {
synchronized (stickyEvents) {
return eventType.cast(stickyEvents.remove(eventType));
}
}
}
其中
class AsyncPoster implements Runnable {
Subscription subscription;
Object event;
//Eventbus的源码中也使用了该线程池
private final static ExecutorService executorService = Executors.newCachedThreadPool();
public AsyncPoster(Subscription subscription, Object event){
this.subscription = subscription;
this.event = event;
}
public static void enqueue(Subscription subscription, Object event) {
AsyncPoster asyncPoster = new AsyncPoster(subscription,event);
// 用线程池
executorService.execute(asyncPoster);
}
@Override
public void run() {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber,event);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
使用
使用方法与原版EventBus一模一样
//发送普通事件
EventBus.getDefault().post("text");
//发送粘性事件
EventBus.getDefault().postSticky("hi");
//注册订阅
EventBus.getDefault().register(this);
// 解绑
EventBus.getDefault().unregister(this);
/**
* threadMode 执行的线程方式
* priority 执行的优先级
* sticky 粘性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN,priority = 50,sticky = true)
public void test1(String msg){
// 如果有一个地方用 EventBus 发送一个 String 对象,那么这个方法就会被执行
Log.e("TAG","msg1 = "+msg);
mTv.setText(msg);
}
/**
* threadMode 执行的线程方式
* priority 执行的优先级,值越大优先级越高
* sticky 粘性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN,priority = 100,sticky = true)
public void test2(String msg){
// 如果有一个地方用 EventBus 发送一个 String 对象,那么这个方法就会被执行
Log.e("TAG","msg2 = "+msg);
mTv.setText(msg);
}