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 , 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线程执行,在此方法中使用反射的机制调用订阅方法。
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内部维护了一个缓存线程池,用来管理线程。
我们在应用时,可以随意切换方法执行的线程,其实其内部原理很简单:
BackGround和Async的区别:
1,background模式中,如果是在主线程post事件,则使用BackGroundPoster新开线程(是线程安全的),如果是在子线程post事件,则直接在该子线程反射invokeSubscribe调用方法,是非线程安全的
2、async模式中,不管post事件是在那里发送的,直接使用AsyncPoster新开线程。(非线程安全的)
上一篇: Android开发之DataBinding的使用 (Kotlin)
下一篇: 事件分发全面认识
推荐阅读
-
spring5 源码深度解析----- 事务的回滚和提交(100%理解事务)
-
Mybaits 源码解析 (六)----- 全网最详细:Select 语句的执行过程分析(上篇)(Mapper方法是如何调用到XML中的SQL的?)
-
Spring源码学习【六】AOP原理解析(一)代理对象的生成
-
Mybaits 源码解析 (七)----- Select 语句的执行过程分析(下篇)全网最详细,没有之一
-
Python3字符串-最容易理解的方式
-
spring5 源码深度解析----- @Transactional注解的声明式事物介绍(100%理解事务)
-
很容易理解的Android AsyncTask源码与工作原理分析
-
超详细的HDFS读写流程详解(最容易理解的方式)
-
最容易理解的Android6.0动态权限申请教程
-
Mybaits 源码解析 (六)----- 全网最详细:Select 语句的执行过程分析(上篇)(Mapper方法是如何调用到XML中的SQL的?)