EventBus3.0最容易理解的源码解析

作为安卓程序员,知其然更要知其所以然,好的工具不应该只停留在会用的层面上,更应该探究其原理,一方面进阶自己,另一方面也是自己在面试中的优势。接下来的源码解析,我不会照搬EventBus的源码进行一行一行解说,那样太晦涩对于新手来说很不友好,我将在我撸了一遍源码的基础上,归纳总结。

一、六大参数解析

首先,在我们使用EventBus.getdefault( )这句代码时,EventBus会帮我们实例化EventBus,并且创建六大参数:

EventBus(EventBusBuilder builder) {
    subscriptionsByEventType = new HashMap<>();
    typesBySubscriber = new HashMap<>();
    stickyEvents = new ConcurrentHashMap<>();
    mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
    backgroundPoster = new BackgroundPoster(this);
    asyncPoster = new AsyncPoster(this);
    //一系列的builder赋值
}

来看看这六大参数的真面目:
1、subscriptionsByEventType :其类型是HashMap>, EventType就是我们发送事件时的参数。例如EventBus.getdefault().post( new Person() );,这个Person类的Class对象就是这个EventType。再看Subscription, Subscription封装了Subscriber(也就是EventBus.getDefault().register(this)注册时传入的this对象)和SubscribMethod(就是使用@Subscribe标注的方法)两个对象。

2、typesBySubscriber :其类型是HashMap>, Subscriber 上边我们已经解释过了,Event就是上边注册时所说的Person对象。(注意:Event和EventType是不一样的!!!)。

3、stickyEvents :其类型是HashMap , 这个主要是用来保存所有的粘性事件的。

4、MainThreadPoster:MainThreadPoster继承Handler,在EventBUs初始化的时候传Looper.getmainLooper()的UI线程Looper对象。MainThreadPoster的enQueue(event)方法会将event加入队列,并调用sendMessage()方法.
MainThreadPoster重写handleMessage方法,handleMessage()方法将在UI线程执行,在此方法中使用反射的机制调用订阅方法。

这里写图片描述

5、BackGroundPoster:实现Runnable接口,内部使用缓存线程池管理线程操作,BackGroundPoster内部的enqueue()方法和run()方法内部都使用了synchronized关键字和Volatile关键字,来确保线程安全。

6、实现了Runnable接口,内部使用缓存线程池管理线程操作,和BackGroundPoster相似,但是他没有使用synchronized关键字和Volatile关键字,是非线程安全的。

二、流程分析

1、初始化 #getDefault()
EventBus3.0使用单例模式,但是同时也提供了public的构造函数,每个EventBus实例都是一条事件总线。在使用 ##EventBus.getDdfault() ##方法时,对上述的六大参数进行初始化
2、注册 #register(subscriber)
注册的流程就是通过subscriber查询所有的method方法。并将这些method和subscriber组合分别存入三个Map数据结构中。
3、发送事件 #post(event)
发送事件并完成线程间的切换的本质是通过反射、Handler的handleMessage()方法、线程池的execute()方法最终实现。EventBus内部维护了一个缓存线程池,用来管理线程。
我们在应用时,可以随意切换方法执行的线程,其实其内部原理很简单:
EventBus3.0最容易理解的源码解析_第1张图片

BackGround和Async的区别:

1,background模式中,如果是在主线程post事件,则使用BackGroundPoster新开线程(是线程安全的),如果是在子线程post事件,则直接在该子线程反射invokeSubscribe调用方法,是非线程安全的
2、async模式中,不管post事件是在那里发送的,直接使用AsyncPoster新开线程。(非线程安全的)

你可能感兴趣的:(源码解析)