这操作真香!三幅图给你弄懂EventBus核心原理

如图所示,一个Subscribe对应多个Event,Subsribe就是上面通过register方法注册的对象,比如activity。这幅图对应EventBus中一个Map结构:

private final Map<Object, List<Class<?>>> typesBySubscriber;

EventBus会在对象register时,使用反射机制,遍历对象的方法,将带有@Subscribe标签并且合法的方法加入到typesBySubscriber。typesBySubscriber是HashMap形式,key是注册的对象本身,由于一个注册的对象中可能有多个监听事件,所以value是用list保存的Event。

看下register方法中如何处理的

public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass(); List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } } } // Must be called in synchronized block private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { List

上面的代码主要做两件事:1、通过反射遍历注册对象的方法,获取其中带有@Subscribe标签的方法并且放在一个列表中,最后以注册对象为key,@Subscribe的方法列表作为value放在HashMap中,就是上图的形式。

思考:

**1、为什么要将注册监听对象作为key,监听事件列表作为value放在HashMap中?**要弄懂一个问题,EventBus是观察者模式,上面的activity也就是subscribe是订阅者,activity中的event是订阅事件,一个订阅者可以订阅多个事件,移除一个订阅者的监听事件时,应该将其中所有的event的事件移除。也就是说在反注册的时候,会通过Subsribe来查找到其中所有额event进行反注册。

第二幅图(订阅事件和订阅者)

这种表关系是event和subsciption的对应关系,比如在Android中多个activity可能会注册监听同一个event事件,所以在执行:

EventBus.getDefault().post(new Event1());

的时候所有注册监听了Event1的监听都会要会收到回调,看下subsciption的结构

subsciption中包含,订阅的事件和订阅者本身,上面中所有的event就是订阅的事件,在Android中订阅的事件代码如下:

@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(Event event) {
}

而subsriber就是订阅者比如会在activity的onstart中执行


EventBus.getDefault().register(this);

那么subsribe就是activity。

思考 为什么需要保存Event和subsribe对应的关系表?

这是因为一个Event可能会有被多个subsribe订阅,所以有当执行post(Event)的时候会查找到所有订阅了Event事件的subscribe并调用其中的event方法。下面看下post方法:

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;
}
}

post和postSticky主要都会调用到上面的方法,上面方法中subscriptionsByEventType.get(eventClass)就是通过event的类型找上面的表中找到对应的subscriptions进行通知的。

第三幅图

在看第三幅图之前思考一个问题,postSticky到底是怎么执行的?为什么先执行postSticky,后执行register还是可以监听到event事件?先看postSticky代码:

public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}

原来执行postSticky的时候会将event.getclass和event保存起来,然后再看下subscribe代码:

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<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet(); for (Map.Entry

先判断注册监听的event是不是sticky的如果是就会用stickEvents表中找到stickyEvent如果如果注册的事件event和stickyEvent一样那么就会执行一次postToSubscription方法,也就是调用注册的方法执行。

总结

Android开发除了flutter还有什么是必须掌握的吗?

相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了

除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

[外链图片转存中…(img-LxHHIbxt-1715154026838)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值