一、概述
在上一节分析了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