标签:pen rate 内存泄漏 poj 状态 udp 不同的 入队 tac
官网定义:EventBus
是一个使用 Java 写的观察者模式,解耦的Android开源库。EventBus 只需要几行代码即可解耦简化代码,加快开发速度。
public class MessageEvent {
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}
// This method will be called when a SomeOtherEvent is posted
@Subscribe
public void handleSomethingElse(SomeOtherEvent event) {
doSomethingWith(event);
}
```
subscribers 需要注册
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
在需要接收时间的地方,通过 @Subscribe
写
Github:https://github.com/greenrobot/EventBus
官网:http://greenrobot.org/eventbus/
从使用的入口开始
发送消息一般调用 post() 方法,然后把定义的 Event 发送出去,看下 post() 方法源码
public void post(Object event) {
// ThreadLocal 中获取变量 postingState.
PostingThreadState postingState = currentPostingThreadState.get();
// 从 postingState 中拿到 ArrayList
List<Object> eventQueue = postingState.eventQueue;
// 把当前 event 加入到 ArrayList 中
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 {
// ArrayList 不为 Null , 循环取出来数据,通过 postSingleEvent() 发送。
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
// Arraylist 中所有的消息都发送完成,设置 isPosting 和 isMainThread 为 false。
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
从 ThreadLocal 中拿到 PostingThreadState ,然后把消息放入的到变量 ArrayList 中,然后判断 postingState 的状态,是否处于发送状态,不在发送状态的话,进入条件判断然后遍历 ArrayList 调用 postSingleEvent() 方法把 event 发送。看下 postSingleEvent() 源码
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
// 订阅者信息是否能找到
boolean subscriptionFound = false;
// 通过 EventBusBilder 传入的, 默认为 true
if (eventInheritance) {
List<Class<?>> 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 {
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));
}
}
}
在方法 postSingleEvent() 中,通过成员变量 eventInheritance (表示是否要向上查找事件的父类) 来判断,默认为 true ,所以进入 if 中,lookupAllEventTypes() 方法会通过递归的方式进行查找所有父类事件并存到 List 中。然后通过遍历调用 postSingleEventForEventType() 方法进行处理
看下 lookupAllEventTypes() 源码,其中 addInterfaces() 通过递归拿到全部的父类事件。
private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
synchronized (eventTypesCache) {
List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
if (eventTypes == null) {
eventTypes = new ArrayList<>();
Class<?> clazz = eventClass;
while (clazz != null) {
eventTypes.add(clazz);
addInterfaces(eventTypes, clazz.getInterfaces());
clazz = clazz.getSuperclass();
}
eventTypesCache.put(eventClass, eventTypes);
}
return eventTypes;
}
}
addInterfaces()
源码,通过递归调用方法,查找所有的父类事件并加入到 List 中
static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {
for (Class<?> interfaceClass : interfaces) {
if (!eventTypes.contains(interfaceClass)) {
eventTypes.add(interfaceClass);
addInterfaces(eventTypes, interfaceClass.getInterfaces());
}
}
}
看下 postSingleEventForEventType()
源码。成员变量 subscriptionsByEventType
是一个 Map<Class<?>, CopyOnWriteArrayList<Subscription>>
, 通过成员变量拿到 subscriptions ,然后遍历该列表,调用 postToSubscription() 方法
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
// 线程安全的ArrayList 保存订阅者信息
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
// 根据 clz 获取该类的订阅者信息列表
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
//遍历订阅者信息列表
for (Subscription subscription : subscriptions) {
//设置 postingState 的状态
postingState.event = event;
postingState.subscription = subscription;
// 是否可以取消,默认不可取消
boolean aborted = false;
try {
// 传入订阅者信息,event, 是否在主线程
postToSubscription(subscription, event, postingState.isMainThread);
// postingState.canceled 默认是 false 。表示不可取消
aborted = postingState.canceled;
} finally {
//postingState 恢复成默认状态。
postingState.event = null;
postingState.subscription = null;
postingState.canceled = false;
}
if (aborted) {
break;
}
}
return true;
}
return false;
}
进入 postToSubscription()
源码,根据订阅者在注册的时候存入的 threadMode
把 event
分发到不同的线程中。根据 threadMode
不同,可以分为 POSTING
, MAIN
, MAIN_ORDERED
, BACKGROUND
, ASYNC
。 变量 mainThreadPoster 其实是 HandlerPoster ,把消息发送到 UI 线程的。
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:// 订阅者与 event 在相同线程
invokeSubscriber(subscription, event);
break;
case MAIN:// UI 线程
// event 是在 UI 线程,则直接通过反射调用。
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
// event 不在 UI 线程,则加入队列,通过 Handler 切换到 UI 线程
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED://UI线程,按照顺序发送消息
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://订阅者单独一个线程,不同于发送线程和UI线程。
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
invokeSubscriber() 方法,通过反射执行订阅者的订阅方法
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);
}
}
标签:pen rate 内存泄漏 poj 状态 udp 不同的 入队 tac
原文地址:https://www.cnblogs.com/liyiran/p/9172989.html