此文章是建立在已经掌握EventBus的使用方法基础上的,不会的参考官网
我们通过2步来讲解,首先是注册、接收回调与发送消息,然后讲解一下解除注册
第一步:
1、注册类:注册与回调方法
EventBus.getDefault().register(this);
/**
* 注解回调的方法
* @param messageEvent
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void optionEvent(MessageEvent messageEvent){
textView.setText(messageEvent.getMessage());
}
此时我们查看一下源码
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
我们知道注册时回调的方法名是可以随便起的,原因就是上面第3句(findSubscriberMethods),有一个方法可以遍历处理此类的所有使用过@Subscribe此注解的方法集合。
接着可以看到,下面是遍历所有需要回调的方法集,调用了subscribe方法,我们来看一下此方法,代码太长我们贴主要代码
Class<?> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
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);
}
}
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;
}
}
这里我们看到有一个subscriptionsByEventType成员变量,此变量是以EventType为key,而Value是Subscription集合,我们通过源码可以看到,这里是通过EventType把所有注册类下面相同参数的方法进行了分组。
也就是说注册类下面有几个接收回调的方法,就有几个Subscription类对象,而且同一个类可以写多个相同结果回调方法,方法名可以不同,源码都会先进行分组后放进subscriptionsByEventType集合中。
2、发送消息
MessageEvent messageEvent = new MessageEvent(editText.getText().toString());
EventBus.getDefault().post(messageEvent);
我们看一下源码
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 = 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;
}
我们可以看到,这里就是遍历subscriptionsByEventType此集合,通过传入的EventType得到所有注册过以此方法为参数的对象,通过反射调用对象下面的方法。
第二步:取消注册
EventBus.getDefault().unregister(this);
我们看一下源码
public synchronized void unregister(Object subscriber) {
List<Class<?>> 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());
}
}
我们可以看到,取消注册是通过遍历typesBySubscriber集合,来把添加到subscriptionsByEventType集合的数值移除掉,然后再从typesBySubscriber移除掉(因为注册传入的是this,所以一定要进行解除注册,否则会造成内存泄漏),我们回头在看一下typesBySubscriber集合,是在注册时集合加入的
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
此集合是以注册类对象为key,EventType为value进行存储,目的就是为了解除注册时方便从subscriptionsByEventType集合中移除注册的方法。
讲到这里,整个EventBus处理的流程是讲完了,这次是第一次完整的自己分析源码,讲一下感受:
当我们要研究一个项目的源码时,开始一定要先会使用此项目,然后通过使用的入口,进行Debug查看调用流程,然后看源码的时候刚开始不要太细钻研每个调用方法是干什么用的,要先理清整个脉络,然后再回头单块攻克主要的成员变量是干什么用的,为什么这么用,如果理不清楚,可以用笔写一下,每个值是干什么用的,真的很有用!!
最后贴一下我梳理时的笔记,字有点丑介意的话,请....你懂得
![](https://img.haomeiwen.com/i1782650/e733629029495a3a.jpg)
网友评论