欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-14 15:26:03
...

作为安卓程序员,知其然更要知其所以然,好的工具不应该只停留在会用的层面上,更应该探究其原理,一方面进阶自己,另一方面也是自己在面试中的优势。接下来的源码解析,我不会照搬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 , List<Subscription>>, EventType就是我们发送事件时的参数。例如EventBus.getdefault().post( new Person() );,这个Person类的Class对象就是这个EventType。再看Subscription, Subscription封装了Subscriber(也就是EventBus.getDefault().register(this)注册时传入的this对象)和SubscribMethod(就是使用@Subscribe标注的方法)两个对象。

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

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

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

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

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最容易理解的源码解析

BackGround和Async的区别:

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