仿EventBus做一个简单的基于订阅发布的事件总线
一、概述
在上一节分析了EventBus的源代码。本节仿照EventBus自己做一个事件总线框架,去掉了一些代码,只保留了核心框架,旨在梳理框架的框架原理,加深对框架流程的理解。
在贴出源代码之前先把这个自定义的EventBus的功能介绍一下。核心流程还是三个,注册、发布、取消注册(未写AnnotationProcessor部分,如果有需要大家可以自己实现),源码中的类绝大部分分仿照了EventBus原有的类名,只是类里面的内容做了简化调整。如:EventBus类只抽离了、post、register、unregister、subscribe方法等。
下面贴出library结构

自己实现的框架其用法和EventBus还是一样的,只是不能发送黏性事假和定义事件的优先级,使用实例代码如下:
public class MainActivity extends AppCompatActivity {
private Button btn;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 注册观察者对象
*/
EventBus.getDefault().register(this);
btn = findViewById(R.id.main_btn);
tv = findViewById(R.id.main_tv);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toPost();
}
});
}
/**
* 用于接收post发送过来的事件
*
* @param event 具体的事件主体
*/
@Subscribe
public void onMessageEvent(MessageEvent event) {
switch (event.getArg1()) {
case 0:
tv.setText("接收小消息为:" + event.getMsg());
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
/**
* 取消订阅
*/
EventBus.getDefault().unRegister(this);
}
/**
* 发送消息
*/
public void toPost() {
MessageEvent event = new MessageEvent();
event.setArg1(0);
event.setMsg("杨洛峋小宝宝来了");
EventBus.getDefault().post(event);
}
}
二、源码介绍以及源码截图
下面提出关键源代码
EventBus.getDefault().register(subscriber)
/**
* 注册
* 订阅方法
*
* @param subscriber
*/
public void register(Object subscriber) {
Class clazz = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = SubscriberMethodFinder.findSubscriberMethods(clazz);
if (subscriberMethods != null && subscriberMethods.size() > 0) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
/**
* 真正的订阅
*
* @param subscriber
* @param subscriberMethod
*/
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class eventType = subscriberMethod.getEventType();
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
}
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size) {
//向订阅集合中加入订阅
subscriptions.add(i, newSubscription);
break;
}
}
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
}
EventBus.getDefault().post(eventObj)
/**
* 发送事件方法
*
* @param eventObj
*/
public void post(Object eventObj) {
PostingThreadState postingThreadState = currentPostingThreadState.get();
List<Object> queue = postingThreadState.getEventQueue();
queue.add(eventObj);
postingThreadState.setMainThread(isMainThread());
//缺少一个发送事件的线程
Class<?> clazz = eventObj.getClass();
List<Subscription> subscriptions = subscriptionsByEventType.get(clazz);
if (subscriptions != null) {
//循环遍历Subscriptions,
for (Subscription subscription : subscriptions) {
//分发事件
postToSubscription(subscription, eventObj, postingThreadState);
}
}
}
/**
* 返回true为主线程,否则为子线程
*
* @return
*/
private boolean isMainThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
/**
* 对事件进行分发
*
* @param subscription
* @param eventTypeObj
*/
private void postToSubscription(Subscription subscription, Object eventTypeObj, PostingThreadState postingThreadState) {
switch (subscription.getSubscriberMethod().getThreadMode()) {
case POSITION:
invokeSubscriber(subscription, eventTypeObj);
break;
case MAIN:
if (isMainThread()) {
invokeSubscriber(subscription, eventTypeObj);
} else {
mainThreadHandlerPoster.enqueue(subscription, eventTypeObj);
}
break;
case MAIN_ORDERD:
if (mainThreadHandlerPoster != null) {
mainThreadHandlerPoster.enqueue(subscription, eventTypeObj);
} else {
invokeSubscriber(subscription, eventTypeObj);
}
break;
case BACKGROUND:
if (backgroundPoster != null) {
backgroundPoster.enqueue(subscription, eventTypeObj);
} else {
invokeSubscriber(subscription, eventTypeObj);
}
break;
case ASYNC:
asyncPoster.enqueue(subscription, eventTypeObj);
break;
}
}
/**
* 执行事件的具体方法
*
* @param subscription
* @param eventTypeObj
*/
public void invokeSubscriber(Subscription subscription, Object eventTypeObj) {
try {
subscription.getSubscriberMethod().getMethod().setAccessible(true);
subscription.getSubscriberMethod().getMethod().invoke(subscription.getSubscriber(), eventTypeObj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
EventBus.getDefault().unRegister(subscriber)
/**
* 取消注册方法
* 取消注册其实就清除两个 集合就行了,一个是Subscriptions集合,一个是typesBySubscriber集合
*
* @param subscriber
*/
public void unRegister(Object subscriber) {
List<Class<?>> eventTypes = typesBySubscriber.get(subscriber);
if (eventTypes != null) {
for (Class<?> clazz : eventTypes) {
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(clazz);
for (Subscription subscription : subscriptions) {
if (subscriber == subscription.getSubscriber()) {
subscriptions.remove(subscription);
}
}
}
typesBySubscriber.remove(subscriber);
}
}
完整的源代码我发布到了github上欢迎大家下载,地址如下:myeventbuslib
浙公网安备 33010602011771号