目录
这是对使用EventBus的记录,如果有错误的地方请多指教,不喜勿喷。
1.项目引用
implementation("org.greenrobot:eventbus:3.3.1")
2.基本用法
class EventBusActivity : AppCompatActivity() {
data class MessageEvent(val msg: String)
/**
* 方法名称可以任意命名
*/
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(msg: MessageEvent) {
Log.d("all_log", "EventBus 订阅事件回调处理。。。")
}
override fun onCreate(savedInstanceState: Bundle?) {
..........
//注册订阅
EventBus.getDefault().register(this)
}
override fun onDestroy() {
..........
//反注册订阅
EventBus.getDefault().unregister(this)
}
}
//发送事件
EventBus.getDefault().post(MessageEvent("消息事件"))
3.源码分析
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
//订阅方法参数类型<eventClass,List<eventClass及父接口类型>>
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
//key:订阅方法的参数类型,value:Subscription(订阅对象,订阅方法)
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//订阅者,跟订阅参数类型集合 typesBySubscriber<订阅对象,list<订阅参数类型>>
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
3.1.注册
EventBus.getDefault().register(this)
通过上面的注册订阅我们来看下EventBus.getDefault()做了什么。
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;
}
通过上面的源码可以看出这就是我们常说的 单例模式 来创建EventBus对象,保证创建出来的对象都是同一个。下面看下创建EventBus的具体过程
//建造模式,配置EventBus的信息
public class EventBusBuilder {
//默认切换到子线程用到的线程池是无限制的,如果大量发送事件可能会OOM
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE =
Executors.newCachedThreadPool();
//>>>>>>> 日志相关
boolean logSubscriberExceptions = true;
boolean logNoSubscriberMessages = true;
boolean sendSubscriberExceptionEvent = true;
boolean sendNoSubscriberEvent = true;
boolean throwSubscriberException;
//子类发送事件,是否需要发送父类事件
boolean eventInheritance = true;
boolean ignoreGeneratedIndex;
boolean strictMethodVerification;
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
List<Class<?>> skipMethodVerificationForClasses;
List<SubscriberInfoIndex> subscriberInfoIndexes;
Logger logger;
MainThreadSupport mainThreadSupport;
}
EventBus(EventBusBuilder builder) {
//日志输出
logger = builder.getLogger();
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
mainThreadSupport = builder.getMainThreadSupport();
//主线程处理
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
//后台线程处理
backgroundPoster = new BackgroundPoster(this);
//异步线程处理
asyncPoster = new AsyncPoster(this);
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
//订阅方法查找类
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
logSubscriberExceptions = builder.logSubscriberExceptions;
logNoSubscriberMessages = builder.logNoSubscriberMessages;
sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
throwSubscriberException = builder.throwSubscriberException;
eventInheritance = builder.eventInheritance;
//线程池配置
executorService = builder.executorService;
}
有了EventBus对象接下来就要注册订阅了
public void register(Object subscriber) {
//订阅对象 如Activity...
Class<?> subscriberClass = subscriber.getClass();
//SubscriberMethod 封装了订阅方法相关信息 如方法,线程类型...
List<SubscriberMethod> subscriberMethods =
//查找订阅的方法
subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//查找到相关订阅方法后 开始订阅
subscribe(subscriber, subscriberMethod);
}
}
}
public class SubscriberMethod {
final Method method; //订阅方法
final ThreadMode threadMode;//线程类型
final Class<?> eventType;//事件类型 --- 订阅的方法参数类型
final int priority;//优先级
final boolean sticky;//是否是粘性订阅
.....
}
现在我们看下 subscriberMethodFinder.findSubscriberMethods(subscriberClass) 具体做了什么。
class SubscriberMethodFinder {
/*
* 缓存订阅对象的方向集合
* key:订阅对应如Activity ,value:是订阅方法集合
*/
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE =
new ConcurrentHashMap<>();
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
//查找到缓存直接返回
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) {
//默认是false 不执行这里 通过运行反射获取
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;
}
}
}
现在看下subscriberMethods = findUsingReflection(subscriberClass);是如何查找订阅方法的
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//通过反射获取订阅方法
findUsingReflectionInSingleClass(findState);
//findState.clazz 定位到位父class
findState.moveToSuperclass();
}
//释放FindState到缓存中 返回订阅方法集合
return getMethodsAndRelease(findState);
}
现在看下 subscriberMethods = findUsingInfo(subscriberClass);是如何查找订阅方法的,
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
//FindState 有复用默认缓存4个
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
/*
* subscriberInfo从SubscriberInfoIndex获取 如果获取不到
* 也是通过反射来获取订阅的方法信息
*/
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);
}
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
findState.recycle();
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
}
return subscriberMethods;
}
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
//订阅类如Activity
Class<?> subscriberClass;
Class<?> clazz;
boolean skipSuperClasses;
SubscriberInfo subscriberInfo;
//初始化下
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
.....
}
现在看下反射的获取方式 findUsingReflectionInSingleClass(findState)
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
try {
methods = findState.clazz.getMethods();
} catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
String msg = "Could not inspect methods of " + findState.clazz.getName();
if (ignoreGeneratedIndex) {
msg += ". Please consider using EventBus annotation processor to avoid reflection.";
} else {
msg += ". Please make this class visible to EventBus annotation processor to avoid reflection.";
}
throw new EventBusException(msg, error);
}
//是否跳过父类
findState.skipSuperClasses = true;
}
for (Method method : methods) {
//方法修饰符 要是public
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
//订阅方法的参数只能一个
if (parameterTypes.length == 1) {
/*
* public @interface Subscribe {
* 线程 默认执行在 当前调用线程
* ThreadMode threadMode() default ThreadMode.POSTING;
* 是否是粘性
* boolean sticky() default false;
* 优先级
* int priority() default 0;
* }
* */
//Subscribe 订阅方法注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
//拿到参数类型class对象
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
//获取注解值
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");
}
}
}
以上就是获取订阅信息的过程,现在订阅信息有了就开始订阅了
subscribe(subscriber, subscriberMethod);
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
//将订阅对象和订阅方法封装成Subscription
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//判断是否添加过,如果添加过就抛出EventBusException
CopyOnWriteArrayList<Subscription> 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);
}
}
//根据优先级 添加Subscription
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;
}
}
//订阅对象 和订阅方法类行 保存在 typesBySubscriber中
//伪代码结构:typesBySubscriber<订阅对象,list<订阅参数类型>>
List<Class<?>> 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<Class>).
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);
}
}
}
总结:订阅的基本流程
3.2 事件的分发
public void post(Object event) {
/*
* private final ThreadLocal<PostingThreadState> currentPostingThreadState =
* new ThreadLocal<PostingThreadState>() {
* @Override
* protected PostingThreadState initialValue() {
* return new PostingThreadState();
* }
* };
*
* final static class PostingThreadState {
* //发送事件队列
* final List<Object> eventQueue = new ArrayList<>();
* boolean isPosting; true:标记当前正在分发事件
* boolean isMainThread;
* Subscription subscription;
* Object event;//消息事件 post(消息事件)
* boolean canceled;
* }
* currentPostingThreadState是ThreadLocal<PostingThreadState>
* ThreadLocal:保存当前线程的Post 状态
*/
PostingThreadState postingState = currentPostingThreadState.get();
//获取当前线程的事件队列
List<Object> eventQueue = postingState.eventQueue;
//把消息加入到队列中
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = isMainThread();
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;
}
}
}
ThreadLocal:可以理解为线程独有的存储区域,不与其他线程共享,Handler中也有用到
现在看下 postSingleEvent(eventQueue.remove(0), postingState);
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
//订阅方法的参数类型
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {
//查找eventClass 的父类及自己的接口类型
// class MessageEvent implements Event
// 那么查找到 MessageEvent和Event
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
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));
}
}
}
接着进入 postSingleEventForEventType(...)
private boolean postSingleEventForEventType(
Object event, //订阅方法参数对象
PostingThreadState postingState, //当前线程的分发状态
//订阅方法参数类型
Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
//获取通过参数类型 获取订阅方法列表
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
boolean aborted;
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;
}
现在到关键的一步,对消息进行分发及线程切换
postToSubscription(subscription, event, postingState.isMainThread)
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
//默认执行线程类型,post在什么线程,就在什么线程分发
invokeSubscriber(subscription, event);
break;
case MAIN:
//主线程 如果在子线程,就用handler切换到主线程
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
//如果主线程mainThreadPoster!=null 就post到主线程中去执行
//否则就在post线程中去执行
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
// temporary: technically not correct as poster not decoupled from subscriber
invokeSubscriber(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);
}
}