美文网首页
更新2019-01-16 EventBus 分析(Android

更新2019-01-16 EventBus 分析(Android

作者: kennychaos | 来源:发表于2019-01-12 18:34 被阅读0次

    闲得发慌,打算自己做一个注解+事件总线的android框架
    就先从分析一下其他框架开始

    贴一下EventBus的github地址

    image

    EventBus特点

    依赖注解(下面是详细在EventBus存在的可注解主题)

    Annotation Feature
    @Subscribe 订阅事件
    ThreadMode Description NOTE
    POSTING 直接执行 直接通过java.lang.reflect包的method.invoke执行(默认)
    MAIN 在主线程执行 EventBus会先判断是否在主线程:是,则直接跟POSTING一样通过method.invoke直接执行;否,则压入mainPoster的队列里
    MAIN_ORDERED 同样是在主线程执行 EventBus压入mainPoster的队列中
    BACKGROUND 后台运行 EventBus会先判断是否在主线程:是,则压入backgroundPoster的队列里;否,则通过method.invoke直接执行
    ASYNC 在单独一个线程中执行 由EventBusBuilder中的newCachedThreadPool执行

    它不像xutils一样,拥有控件和控件事件上的注解
    不过毕竟是可以跨android和Java的框架

    EventBus is a publish/subscribe event bus for Android and Java.

    也就不强求这个了(熟悉一下ClassLoader和InvocationHandlr,也可以自己加这些)

    事件管理

    这个事件的管理囊括了多线程,CopyOnWriteArrayList(java的concurrent包的一个优化算法),它自己建的队列PendingPostQueue,注解事件监听。

    ok,那么详细来分析一下这个框架的源码

    有几个重要的类或者接口需要看一下

    1. EventBus和对应的建造者EventBusBuilder

    2. 各种事件Poster

    EventBus的实现是典型的建造者模式(当然也有一些工厂模式和代理模式在里面)

    public static EventBusBuilder builder() {
          //返回一个新建的EventBusBuilder对象
          return new EventBusBuilder();
        }
    

    在EventBusBuilder的中,创建了一个默认的可无线扩容的线程池newCachedThreadPool

    //在EventBusBuilder中
      private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
    ...
      public EventBusBuilder executorService(ExecutorService executorService) {
            this.executorService = executorService;
            return this;
        }
    ...
    //在异步事件AsyncPoster中
     public void enqueue(Subscription subscription, Object event) {
            PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
            queue.enqueue(pendingPost);
            eventBus.getExecutorService().execute(this);
        }
    ...
    //在后台事件BackgroundPoster中
      public void enqueue(Subscription subscription, Object event) {
            PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
            synchronized (this) {
                queue.enqueue(pendingPost);
                if (!executorRunning) {
                    executorRunning = true;
                    eventBus.getExecutorService().execute(this);
                }
            }
        }
    

    这个线程主要负责异步事件AsyncPoster和后台事件BackgroundPoster的执行,但在EventBus里还有POSTING,MAIN,MAIN_ORDERED这三个事件,那么它们又是靠什么线程来执行的呢?

    这三者其实是基本一致的
    只不过是MAIN和MAIN_ORDERED事件会先过一个isMainThread()方法

      private boolean isMainThread() {
            return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true;
      }
    

    那么它是怎么将事件放在主线程运行呢?

    首先介绍一下Looper这个东西
    简单点理解,Looper其实就是一个死循环,不停遍历内部是否含有未处理的Runnable
    也是就是执行消息循环队列MessageQueue的一个线程
    而且默认情况下,我们后来新建的线程都是没带消息循环队列MessageQueue

    //创建一个Looper对象
    Looper.prepare();
    //开始执行Looper.loop
    Looper.loop();
    //返回主线程的Looper对象
    Looper.getMainLooper();
    

    这里我们就可以做是否主线程的判断了,但还是没有明白怎么把事件发到主线程上

    其实这里应该补充一个东西,HandlerThread & Handler的原理了
    (如果你有看过tensorflow的官方demo,就可以发现它的识别线程其实就是一个基于主线程Looper创建的一个HandlerThread)

    //HandlerThread其实也是多线程的一种,只不过其他多线程基本都是java自带的,不存在Looper
    //而HandlerThread是存于android.os包里的,带了Looper
    HandlerThread handlerThread = new HandlerThread("线程名称");
    //只有在启动这个线程,对应的Looper对象才能被生成,然后才可以创建以此Looper为底的handler(个人理解,可以把handler当作是Looper的一个外露接口)
    handlerThread.start();
    //以此Looper为底的handler
    Handler handler = new Handler(handlerThread.getLooper());
    OR
    //以此Looper为底的handler,并且处理消息的分发
    Handler handler = new Handler(handlerThread.getLooper(),new Handler.Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                      ...
                      return false;
                }
            });
    

    虽然,EventBus并没有用HandlerThread.....只是用了 Handler handler = new Handler(Looper.getMainLooper()); 而已!

    EventBus的所有事件Poster基本都实现了Runnable(除了MAIN和MAIN_ORDERED事件外,这两个都拿去继承了Handler和实现Poster接口而已)
    当然在每个事件Poster都有一个PendingPostQueue(EventBus自建带同步锁和延迟弹出的队列)在存储需要发送的消息(ps:下回再讲)

      /*提取消息准备发送*/
      /*@param event  为开发者自己创建需要传递的消息*/
      static PendingPost obtainPendingPost(Subscription subscription, Object event) {
            /*pendingPostPool为存储的消息的数组*/
            synchronized (pendingPostPool) {
                int size = pendingPostPool.size();
                if (size > 0) {
                    PendingPost pendingPost = pendingPostPool.remove(size - 1);
                    pendingPost.event = event;
                    pendingPost.subscription = subscription;
                    pendingPost.next = null;
                    return pendingPost;
                }
            }
            return new PendingPost(event, subscription);
        }
    

    未完待续...

    相关文章

      网友评论

          本文标题:更新2019-01-16 EventBus 分析(Android

          本文链接:https://www.haomeiwen.com/subject/gjbtdqtx.html