自己动手写事件总线(EventBus) (2)

执行过这些逻辑后,该对象所有的观察者方法都会被存在一个Map中,其Key是EventType,即观察事件的类型,Value是订阅了该类型事件的所有方法(即观察者)的一个列表,每个方法和对象一起封装成了一个Subscription类:

public class Subscription { public final Reference<Object> subscriber; public final SubscriberMethod subscriberMethod; public Subscription(Object subscriber, SubscriberMethod subscriberMethod) { this.subscriber = new WeakReference<>(subscriber);// EventBus3 没用弱引用? this.subscriberMethod = subscriberMethod; } @Override public int hashCode() { return subscriber.hashCode() + subscriberMethod.methodString.hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof Subscription) { Subscription other = (Subscription) obj; return subscriber == other.subscribe && subscriberMethod.equals(other.subscriberMethod); } else { return false; } } }

如此,便是注册监听方法的核心逻辑了。

消息发送

消息的发送代码很简单:

public class EventBus { ... private EventDispatcher mEventDispatcher = new EventDispatcher(); private ThreadLocal<Queue<EventType>> mThreadLocalEvents = new ThreadLocal<Queue<EventType>>() { @Override protected Queue<EventType> initialValue() { return new ConcurrentLinkedQueue<>(); } }; ... public void post(Object message) { if (message == null) { return; } mThreadLocalEvents.get().offer(new EventType(message.getClass())); mEventDispatcher.dispatchEvents(message); } ... }

比较复杂一点的是需要根据注解声明的线程模式在对应的线程进行发布:

public class EventBus { ... private class EventDispatcher { private IEventHandler mMainEventHandler = new MainEventHandler(); private IEventHandler mPostEventHandler = new DefaultEventHandler(); private IEventHandler mAsyncEventHandler = new AsyncEventHandler(); void dispatchEvents(Object message) { Queue<EventType> eventQueue = mThreadLocalEvents.get(); while (eventQueue.size() > 0) { handleEvent(eventQueue.poll(), message); } } private void handleEvent(EventType eventType, Object message) { List<Subscription> subscriptions = mSubscriptionsByEventtype.get(eventType); if (subscriptions == null) { return; } for (Subscription subscription : subscriptions) { IEventHandler eventHandler = getEventHandler(subscription.subscriberMethod.threadMode); eventHandler.handleEvent(subscription, message); } } private IEventHandler getEventHandler(ThreadMode mode) { if (mode == ThreadMode.ASYNC) { return mAsyncEventHandler; } if (mode == ThreadMode.POST) { return mPostEventHandler; } return mMainEventHandler; } }// end of the class ... }

三种线程模式分别如下,DefaultEventHandler(在发布线程执行观察者放方法):

public class DefaultEventHandler implements IEventHandler { @Override public void handleEvent(Subscription subscription, Object message) { if (subscription == null || subscription.subscriber.get() == null) { return; } try { subscription.subscriberMethod.method.invoke(subscription.subscriber.get(), message); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } }

MainEventHandler(在主线程执行):

public class MainEventHandler implements IEventHandler { private Handler mMainHandler = new Handler(Looper.getMainLooper()); DefaultEventHandler hanlder = new DefaultEventHandler(); @Override public void handleEvent(final Subscription subscription, final Object message) { mMainHandler.post(new Runnable() { @Override public void run() { hanlder.handleEvent(subscription, message); } }); } }

AsyncEventHandler(新开一个线程执行):

public class AsyncEventHandler implements IEventHandler { private DispatcherThread mDispatcherThread; private IEventHandler mEventHandler = new DefaultEventHandler(); public AsyncEventHandler() { mDispatcherThread = new DispatcherThread(AsyncEventHandler.class.getSimpleName()); mDispatcherThread.start(); } @Override public void handleEvent(final Subscription subscription, final Object message) { mDispatcherThread.post(new Runnable() { @Override public void run() { mEventHandler.handleEvent(subscription, message); } }); } private class DispatcherThread extends HandlerThread { // 关联了AsyncExecutor消息队列的Handle Handler mAsyncHandler; DispatcherThread(String name) { super(name); } public void post(Runnable runnable) { if (mAsyncHandler == null) { throw new NullPointerException("mAsyncHandler == null, please call start() first."); } mAsyncHandler.post(runnable); } @Override public synchronized void start() { super.start(); mAsyncHandler = new Handler(this.getLooper()); } } }

以上便是发布消息的代码。

注销监听

最后一个对象被销毁还要注销监听,否则容易导致内存泄露,目前SimpleEventBus用的是WeakReference,能够通过GC自动回收,但不知道greenrobot/EventBus为什么没这样实现,待研究。注销监听其实就是遍历Map,拿掉该对象的订阅即可:

public class EventBus { ... public void unregister(Object subscriber) { if (subscriber == null) { return; } Iterator<CopyOnWriteArrayList<Subscription>> iterator = mSubscriptionsByEventtype.values().iterator(); while (iterator.hasNext()) { CopyOnWriteArrayList<Subscription> subscriptions = iterator.next(); if (subscriptions != null) { List<Subscription> foundSubscriptions = new LinkedList<>(); for (Subscription subscription : subscriptions) { Object cacheObject = subscription.subscriber.get(); if (cacheObject == null || cacheObject.equals(subscriber)) { foundSubscriptions.add(subscription); } } subscriptions.removeAll(foundSubscriptions); } // 如果针对某个Event的订阅者数量为空了,那么需要从map中清除 if (subscriptions == null || subscriptions.size() == 0) { iterator.remove(); } } } ... }

以上便是事件总线最核心部分的代码实现,完整代码见vimerzhao/SimpleEventBus,后面发现问题更新或者进行升级也只会改动仓库的代码。

局限性

由于时间关系,目前只研究了EventBus的核心部分,还有几个值得深入研究的点,在此记录一下,也欢迎路过的大牛指点一二。

性能问题

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyyddz.html