使用
github地址:
https://github.com/greenrobot/EventBus
引入
implementation 'org.greenrobot:eventbus:3.0.0'
订阅和接收
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN,priority = 100,sticky = true)
public void onStringEvent(String event) {
Log.d("接收者", "event----:" + event);
}
发布事件
EventBus.getDefault().post("我来发布消息");
发布粘性事件
EventBus.getDefault().postSticky("我来发布消息");
ThreadMode总共四个枚举项:
MAIN //UI主线程
BACKGROUND //后台线程
POSTING //和发布者处在同一个线程
ASYNC //异步线程
终止事件往下传递:
//优先级高的订阅者可以终止事件往下传递
EventBus.getDefault().cancelEventDelivery(event);
混淆
-keepattributes *Annotation*
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
源码分析
第一步register
第一步:EventBus.getDefault().register(this);其中getDefault()获取单例,看EventBus中register()方法:
public void register(Object subscriber) {
//首先获得class对象
Class<?> subscriberClass = subscriber.getClass();
//通过findSubscriberMethods来找到订阅者订阅了哪些事件,返回一个SubscriberMethod对象的List。
//SubscriberMethod里包含了:这个对象的方法method、响应订阅的线程ThreadMode、方法参数类型eventType、订阅的优先级 priority、是否接收粘性sticky的boolean值。
//其实就是解析这个类上的所有带@Subscriber注解的方法的属性。
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
// 订阅,第二步分析
subscribe(subscriber, subscriberMethod);
}
}
}
看SubscriberMethodFinder类中findSubscriberMethods(Class<?> subscriberClass)方法:
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
// 先从缓存里面读取,订阅者的Class
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
// ignoreGeneratedIndex属性表示是否忽略注解器生成的MyEventBusIndex。
// 支持编译时注解的方式,需要引入eventbus的apt,ignoreGeneratedIndex的默认值为false,可以通过EventBusBuilder来设置它的值
if (ignoreGeneratedIndex) {
// 利用反射来获取订阅类中所有订阅方法信息
subscriberMethods = findUsingReflection(subscriberClass);
} else {
// 从注解器生成的MyEventBusIndex类中获得订阅类的订阅方法信息
subscriberMethods = findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
会走到SubscriberMethodFinder类中findUsingInfo(Class<?> subscriberClass)方法:
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
// FindState涉及到享元设计模式
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//默认是空,除非用了编译时注解
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
for (SubscriberMethod subscriberMethod : array) {
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {
//走到这里,通过反射去找
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
// 释放 findState 享元模式
return getMethodsAndRelease(findState);
}
走到SubscriberMethodFinder类中findUsingReflectionInSingleClass(FindState findState)方法:
//找方法的核心代码
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// 通过反射来获取订阅类的所有方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
//for循环所有方法
for (Method method : methods) {
// 获取方法访问修饰符
int modifiers = method.getModifiers();
//找到所有声明为public的方法
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
//获取参数的的Class
Class<?>[] parameterTypes = method.getParameterTypes();
//只允许包含一个参数
if (parameterTypes.length == 1) {
//Subscribe注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
//获取事件的Class ,也就是方法参数的Class
Class<?> eventType = parameterTypes[0];
// 检测添加
if (findState.checkAdd(method, eventType)) {
//获取ThreadMode
ThreadMode threadMode = subscribeAnnotation.threadMode();
// 往集合里面添加 SubscriberMethod ,解析方法注解所有的属性
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException("@Subscribe method " + methodName +
"must have exactly 1 parameter but has " + parameterTypes.length);
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
第一步总结:
register()方法中调用findSubscriberMethods(),去解析注册者对象的所有方法,找出public方法,并且带有@Subscribe注解、并且参数只有一个,的方法,然后通过Annotation解析所有细节参数threadMode(线程)、priority(优先级)、sticky(是否粘性)、method(方法名)、eventType(方法参数类型),把这些参数封装成一个SubscriberMethod对象,添加到集合返回。
第二步register
EventBus中register()方法调用了subscribe(subscriber, subscriberMethod);其中subscriber就是register(this)中的this,subscriberMethod就是第一步中的集合遍历的元素对象。
EventBus中subscribe(Object subscriber, SubscriberMethod subscriberMethod)方法:
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
// 获取方法参数的class
Class<?> eventType = subscriberMethod.eventType;
// 创建一个 Subscription,subscribe方法的参数传给了Subscription
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
// 获取订阅了此事件类的所有订阅者信息列表,下面有分析subscriptionsByEventType
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
// 线程安全的 ArrayList
subscriptions = new CopyOnWriteArrayList<>();
// 添加
subscriptionsByEventType.put(eventType, subscriptions);
} else {
// 是否包含,如果包含再次添加抛异常
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
// 处理优先级priority
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
// 通过 subscriber 获取 List<Class<?>>,下面有分析typesBySubscriber
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
// 将此事件类加入 订阅者事件类列表中
subscribedEvents.add(eventType);
// 处理粘性事件
if (subscriberMethod.sticky) {
if (eventInheritance) {
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
查看subscriptionsByEventType,是EventBus的一个Map成员变量,可以根据EventType查找订阅事件
// key 是注解方法参数的class(eventType),value 存放的是Subscription的线程安全的集合列表
//Subscription 包含两个属性,一个是subscriber 订阅者(this),一个是SubscriberMethod注解方法的所有属性参数值(SubscriberMethod)
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
查看typesBySubscriber,是EventBus的一个Map成员变量,根据我们的订阅对象找到EventType。
// key 是所有的订阅者(this),value 是所有订阅者里面方法的参数的class的集合
private final Map<Object, List<Class<?>>> typesBySubscriber;
粘性事件stickyEvents:是ConcurrentHashMap集合,粘性事件的缓存。
第二步总结:
register()方法中调用subscribe方法,解析所有SubscriberMethod的eventType,然后按照要求解析成Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType和Map<Object, List<Class<?>>> typesBySubscriber。
第三步post
查看EventBus中post方法:
public void post(Object event) {
// currentPostingThreadState是一个 ThreadLocal,他的特点是获取当前线程一份独有的变量数据,不受其他线程影响。
PostingThreadState postingState = currentPostingThreadState.get();
// postingState 就是获取到的线程独有的变量数据
List<Object> eventQueue = postingState.eventQueue;
// 把post的事件添加到事件队列
eventQueue.add(event);
// 如果没有处在事件发布状态,那么开始发送事件并一直保持发布状态
if (!postingState.isPosting) {
//是否是主线程
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
//isPosting = true
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {
//走到这里,下面有分析
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
查看EventBus中postSingleEvent方法:
//参数event是post的对象
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
//得到事件的Class
Class<?> eventClass = event.getClass();
//是否找到订阅者
boolean subscriptionFound = false;
//如果支持事件继承,默认为支持
if (eventInheritance) {
//查找 eventClass 的所有父类和接口
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
// 依次向 eventClass 的父类或接口的订阅方法发送事件
// 只要有一个事件发送成功,返回 true ,那么 subscriptionFound 就为 true,下面有分析
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
// 发送事件
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
// 如果没有订阅者
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
查看EventBus中postSingleEventForEventType方法:
//event是post的对象,eventClass是post的对象的class
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
// subscriptionsByEventType是第二步中的map,得到Subscription集合List
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
// 遍历subscriptions
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
// 发送事件,下面分析
postToSubscription(subscription, event, postingState.isMainThread);
// 是否被取消了
aborted = postingState.canceled;
} finally {
postingState.event = null;
postingState.subscription = null;
postingState.canceled = false;
}
// 如果被取消,则跳出循环
if (aborted) {
break;
}
}
return true;
}
return false;
}
查看EventBus中postToSubscription方法:
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
// 根据不同的线程模式执行对应
switch (subscription.subscriberMethod.threadMode) {
// 和发送事件处于同一个线程
case POSTING:
invokeSubscriber(subscription, event);
break;
// 主线程
case MAIN:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
// 子线程,如果发布事件的线程是主线程,那么调用线程池中的子线程来执行订阅方法;否则直接执行;
case BACKGROUND:
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
// 异步线程:无论发布事件执行在主线程还是子线程,都利用一个异步线程来执行订阅方法
case ASYNC:
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
第三步总结:post()方法中去遍历了
subscriptionsByEventType,找到符合的方法,调用方法的method.invoke()执行。
第四步unregister
unregister就是移除。查看EventBus中unregister方法:
public synchronized void unregister(Object subscriber) {
// 获取订阅对象的所有订阅事件类列表,第二步中的map
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
// 将订阅者的订阅信息移除,下面分析
unsubscribeByEventType(subscriber, eventType);
}
// 将订阅者从列表中移除
typesBySubscriber.remove(subscriber);
} else {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
查看EventBus中unsubscribeByEventType方法:
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
// 获取事件类的所有订阅信息列表,将订阅信息从订阅信息集合中移除,同时将订阅信息中的active属性置为FALSE,第二步中的map
List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber) {
// 将订阅信息激活状态置为FALSE
subscription.active = false;
// 将订阅信息从集合中移除
subscriptions.remove(i);
i--;
size--;
}
}
}
}
手写实现
https://github.com/AdamRight/TeaTool/blob/master/app/src/main/java/com/tea/teatool/teaeventbus