EventBus是针一款对Android的发布/订阅事件总线。它可以让我们很轻松的实现在Android各个组件之间传递消息,并且代码的可读性更好,耦合度更低。
优点
代码的简洁性
不依赖于context
可以指定处理事件的线程,线程切换很方便
父类对通知的监听与处理可继承给子类
通知的优先级
黏性事件,可以在事件订阅前发送
缺点:
对代码逻辑分析增加难度
观察者可能会造成接口的膨胀
不支持跨进程
BroadcastReceiver
与android系统进行相关的通知,还是要选择本地广播
需要使用Context和intent等对象
本地广播是相对消耗时间、空间最多的一种方式
可以跨进程
一.基本使用
1.Gradle文件中导入
implementation 'org.greenrobot:eventbus:3.1.1'
2.在需要订阅事件的地方注册事件
EventBus.getDefault().register(this);
3.发送事件
public class MessageEvent {
String message;
}
//发送普通事件
EventBus.getDefault().post(messageEvent);
//发送黏性事件
EventBus.getDefault().postSticky(messageEvent)
4.接收并处理事件
@Subscribe(threadMode = ThreadMode.PostThread)
public void onEvent(MessageEvent messageEvent) {
...
}
5.取消订阅
EventBus.getDefault().unregister(this);
在3.0之前,EventBus还没有使用注解方式。消息处理的方法也只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,分别代表四种线程模型。而在3.0之后,消息处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为PostThread),注意,事件处理函数的访问权限必须为public,否则会报异常。
在EventBus中的观察者通常有四种线程模型,分别是PostThread(默认)、MainThread、BackgroundThread与Async。
PostThread:如果使用事件处理函数指定了线程模型为PostThread,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。
MainThread:如果使用事件处理函数指定了线程模型为MainThread,那么不论事件是在哪个线程中发布出来的,该事件处理函数都会在UI线程中执行。
BackgroundThread:如果使用事件处理函数指定了线程模型为BackgroundThread,那么如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。
Async:如果使用事件处理函数指定了线程模型为Async,那么无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。
EventBus还支持发送黏性事件。简单讲,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。
发送黏性事件EventBus.getDefault().postSticky(new MessageEvent(“test”));
二.实现原理
从EventBus的注册说起
//获取EventBus的实例 单例模式
public static EventBus getDefault() {
EventBus instance = defaultInstance;
if (instance == null) {
synchronized (EventBus.class) {
instance = EventBus.defaultInstance;
if (instance == null) {
instance = EventBus.defaultInstance = new EventBus();
}
}
}
return instance;
}
1.EventBus的register()方法
public void register(Object subscriber) {
//获取订阅事件的类的class
Class> subscriberClass = subscriber.getClass();
//找到该类所有订阅事件的方法
List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
//遍历订阅的方法
for (SubscriberMethod subscriberMethod : subscriberMethods) {
// 对订阅方法进行注册
subscribe(subscriber, subscriberMethod);
}
}
}
SubscriberMethodFinder的findSubscriberMethods()方法
//METHOD_CACHE 为存储着订阅事件的类 以及它对应的所有订阅事件的方法
private static final Map, List> METHOD_CACHE = new ConcurrentHashMap<>();
List findSubscriberMethods(Class> subscriberClass) {
//从缓存中获取
List subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//默认走这里
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()方法
private List 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);
}
//获取当前类的父类直到返回为null则跳出循环,findState.clazz=clazz.getSuperclass()
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
SubscriberMethodFinder的findUsingReflectionInSingleClass()方法
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// 获取该类中声明的所有方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
//获取方法的参数
Class>[] parameterTypes = method.getParameterTypes();
//检查是否只有一个参数 只接收一个参数
if (parameterTypes.length == 1) {
//获取方法的Subscribe注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class> eventType = parameterTypes[0];
//
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
//将方法相关信息(Method,参数类型,TheadMode,优先级,是否是黏性事件) 封装到SubscriberMethod对象中
//再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");
}
}
}
FindState相关类方法
static class FindState {
//缓存subscriberClass类对应订阅方法的集合
final List subscriberMethods = new ArrayList<>();
final Map anyMethodByEventType = new HashMap<>();
final Map subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class> subscriberClass;
Class> clazz;
boolean skipSuperClasses;
SubscriberInfo subscriberInfo;
void initForSubscriber(Class> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
boolean checkAdd(Method method, Class> eventType) {
// 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
// Usually a subscriber doesn't have methods listening to the same event type.
Object existing = anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true;
} else {
if (existing instanceof Method) {
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
.........................................................................................................................
void moveToSuperclass() {
if (skipSuperClasses) {
clazz = null;
} else {
clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
/** 排除java和android系统包下的类 */
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
clazz = null;
}
}
}
}
EventBus的subscribe()方法
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class> eventType = subscriberMethod.eventType;
//将订阅类与订阅的方法封装到Subscription 对象中
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
// 尝试从缓存中根据事件类型来获取所有的Subscription对象
CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
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;
}
}
// 获取该订阅者对应的所有事件类型
List> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
// 如果是黏性事件
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List).
Set, Object>> entries = stickyEvents.entrySet();
for (Map.Entry, 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);
}
}
}
2.EventBus的post()方法
private final ThreadLocal currentPostingThreadState = new ThreadLocal() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
public void post(Object event) {
// 这里从线程局部变量中取出当前线程的状态信息
PostingThreadState postingState = currentPostingThreadState.get();
List
EventBus的postSingleEvent()方法
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {
List> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class> clazz = eventTypes.get(h);
//最终执行postSingleEventForEventType()方法
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
//最终执行postSingleEventForEventType()方法
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
EventBus的postSingleEventForEventType()方法
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class> eventClass) {
CopyOnWriteArrayList subscriptions;
synchronized (this) {
//找到该事件类型的所有订阅方法
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
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 {
//实际上是调用了主线程的Hander的sendMessage()方法
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
if (mainThreadPoster != null) {
//mainThreadPoster继承HanderPoster,HanderPoster继承自Hander ,HanderPoster中的Looper为主线程的Looper
//mainThreadPoster实际上是一个主线程的Handler对象,enqueue()方法最终调用sendMessage()方法
//接着调用handleMessage()方法 该方法中调用eventBus.invokeSubscriber()方法
//将事件切换到主线程
mainThreadPoster.enqueue(subscription, event);
} else {
// temporary: technically not correct as poster not decoupled from subscriber
invokeSubscriber(subscription, event);
}
break;
case BACKGROUND:
if (isMainThread) {
//backgroundPoster实现了Runnable接口
//获取线程池对象并执行runnable任务,eventBus.getExecutorService().execute(this);
//接着在run()方法中调用eventBus.invokeSubscriber()方法
//切换到工作线程
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case ASYNC:
//asyncPoster实现了Runnable接口
//获取线程池对象并执行runnable任务,eventBus.getExecutorService().execute(this);
//接着在run()方法中调用eventBus.invokeSubscriber()方法
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
invokeSubscriber()方法通过反射实现
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost);
if (subscription.active) {
invokeSubscriber(subscription, event);
}
}
void invokeSubscriber(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
线程的切换
首先看EventBusBuilder类
public class EventBusBuilder {
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
.......................................
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
.......................................
//存储着主线程的Looper
MainThreadSupport mainThreadSupport;
........................................
//可以自定义ExecutorService对象
public EventBusBuilder executorService(ExecutorService executorService) {
this.executorService = executorService;
return this;
}
MainThreadSupport getMainThreadSupport() {
if (mainThreadSupport != null) {
return mainThreadSupport;
} else if (AndroidLogger.isAndroidLogAvailable()) {
Object looperOrNull = getAndroidMainLooperOrNull();
return looperOrNull == null ? null :
new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
} else {
return null;
}
}
Object getAndroidMainLooperOrNull() {
try {
//获取了主线程的Looper对象
return Looper.getMainLooper();
} catch (RuntimeException e) {
// Not really a functional Android (e.g. "Stub!" maven dependencies)
return null;
}
}
}
MainThreadSupport类保存着一个主线程的Looper对象
public interface MainThreadSupport {
boolean isMainThread();
Poster createPoster(EventBus eventBus);
class AndroidHandlerMainThreadSupport implements MainThreadSupport {
private final Looper looper;
public AndroidHandlerMainThreadSupport(Looper looper) {
this.looper = looper;
}
//判断是否在主线程
@Override
public boolean isMainThread() {
return looper == Looper.myLooper();
}
@Override
public Poster createPoster(EventBus eventBus) {
//HandlerPoster extends Handler 这里创建了一个主线程的Handler对象
return new HandlerPoster(eventBus, looper, 10);
}
}
}
HandlerPoster类
public class HandlerPoster extends Handler implements Poster {
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
//主线程发送消息
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
}
}
//在主线程中调用订阅方法
eventBus.invokeSubscriber(pendingPost);
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
}
取消订阅 (数据移除)将订阅事件的类从Map中移除 清空订阅事件的类相关订阅方法和订阅类型
public synchronized void unregister(Object subscriber) {
List> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class> eventType : subscribedTypes) {
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}