仿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

原文地址:https://www.cnblogs.com/tony-yang-flutter/p/12463490.html