EventBus源码阅读

『EventBus对于Android开发老司机来说肯定不会陌生,它是一个基于观察者模式的事件发布/订阅框架,开发者可以通过极少的代码去实现多个模块之间的通信,而不需要以层层传递接口的形式去单独构建通信桥梁。从而降低因多重回调导致的模块间强耦合,同时避免产生大量内部类。它拥有使用方便,性能高,接入成本低和支持多线程的优点,实乃模块解耦、代码重构必备良药。』

摘自

https://segmentfault.com/a/1190000005089229?utm_source=tuicool&utm_medium=referral

其实这篇链接已经基本概括使用EventBus涉及到的问题。

这篇通过分析源码,可以了解整个EB的分发过程:

http://skykai521.github.io/2016/02/20/EventBus-3-0%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/

以下是我在应用EB过程中的总结:

在3.0之前,注册监听需要区分是否监听黏性(sticky)事件,监听EventBus事件的模块需要实现以onEvent开头的方法。如今改为在方法上添加注解的形式,注解配置模式,事件优先级,是否粘性事件

@Subscribe(threadMode = ThreadMode.POSTING, priority = 0, sticky = true)

public void handleEvent(DriverEvent event) {

Log.d(TAG, event.info);

}

在postToSubscription()通过不同的threadMode在不同的线程里invoke()订阅者的方法,ThreadMode共有四类:

PostThread:默认的 ThreadMode,表示在执行 Post 操作的线程直接调用订阅者的事件响应方法,不论该线程是否为主线程(UI 线程)。当该线程为主线程时,响应方法中不能有耗时操作,否则有卡主线程的风险。适用场景:对于是否在主线程执行无要求,但若 Post 线程为主线程,不能耗时的操作;

MainThread:在主线程中执行响应方法。如果发布线程就是主线程,则直接调用订阅者的事件响应方法,否则通过主线程的 Handler 发送消息在主线程中处理——调用订阅者的事件响应函数。显然,MainThread类的方法也不能有耗时操作,以避免卡主线程。适用场景:必须在主线程执行的操作;

BackgroundThread:在后台线程中执行响应方法。如果发布线程不是主线程,则直接调用订阅者的事件响应函数,否则启动唯一的后台线程去处理。由于后台线程是唯一的,当事件超过一个的时候,它们会被放在队列中依次执行,因此该类响应方法虽然没有PostThread类和MainThread类方法对性能敏感,但最好不要有重度耗时的操作或太频繁的轻度耗时操作,以造成其他操作等待。适用场景:操作轻微耗时且不会过于频繁,即一般的耗时操作都可以放在这里;

Async:不论发布线程是否为主线程,都使用一个空闲线程来处理。和BackgroundThread不同的是,Async类的所有线程是相互独立的,因此不会出现卡线程的问题。适用场景:长耗时操作,例如网络访问。

由官方文档和实际demo实践可知,EB具体响应哪个事件,只与发送的事件(本质是个对象)的类型有关。也就是说,

订阅四种事件(注解里写明模式,此处以方法名区分)

onPostingEvent、onMainEvent、onBackgroundEvent、onAsyncEvent

订阅者在接收事件时,只以参数(事件类型)为准。

现订阅以下三种方法(默认posting,优先级0,不是粘性事件)

@Subscribe(threadMode = ThreadMode.Main, priority = 0, sticky = true)

public void onMainEvent (AEvent a) {

Log.d(TAG, “main ”+a.info);

}

@Subscribe(threadMode = ThreadMode.Main, priority = 0, sticky = true)

public void onMainEvent (BEvent b) {

Log.d(TAG, “main ”+b.info);

}

@Subscribe(threadMode = ThreadMode.Async, priority = 0, sticky = true)

public void onAsyncEvent (AEvent a) {

Log.d(TAG, “async ”+a.info);

}

当某发送AEvent事件时,实际上会打印两条消息

“main ”+a.info 和 “async ”+a.info

而不是根据某发送事件时-某所处的进程来判断。

不会出现,某在main发送AEvent,接收“main ”+a.info,

而在async发送AEvent,响应“async ”+a.info 的情况。

框架设计思路:

在设计框架,BaseActivity/BaseFragment的时候,应当把订阅的事件(四种)明晰,定义相对应的四种事件,MainEvent,PostEvent,BackgroundEvent,AsyncEvent

,这样的设计,减少多次使用handler调度线程,因为EventBus已经处理过一次线程了。

如果MainEvent有多个行为,设计Mainevent事件类的时候,添加一个mainEventType参数,发送时就指定某事件交给哪个线程处理,哪个线程处理哪些不同的动作,

onMainEvent(MainEvent main){

switch(main.getType){

case type1:

…..

default:

break;

}

没有必要onMainEvent(A),onMainEvent(B),onMainEvent(C)

这样要写三个类,又都是Main进程处理,代码冗余。

拆轮子—注解Annotation

注解demo解析,这篇很直接的讲了怎样去看,去定义一个注解,暴力直白。

http://www.cnblogs.com/yydcdut/p/4646454.html

这个循序渐进,由浅入深的从含义到调用,虽稍显啰嗦,但是很值得慢慢看。

http://blog.csdn.net/lmj623565791/article/details/43452969

我用我的中二理解来描述注解。

程序员---魔法师;

代码里的method、function、方法---武器;

元Annotation---元素;

@Retention, @Target, @Inherited, @Documented

标准Annotation---基础附魔;

Override, Deprecated, SuppressWarnings

自定义Annotation---自定义附魔;

众所周知,在打造武器的时候,附魔总是能够给武器加上不可思议的效果。

而附魔受附魔元素,附魔环境的影响,

通过组合不同的元素(甚至不同形态的元素,如水和冰)创造不同的附魔效果,定义附魔环境,

最后喊出法术名称,给武器附魔。

-----------------------------------0:附魔解析-------------------------------

比如标准注解(标准附魔)Override的定义是:

image

代表的含义,这是一个不被继承的,用于描述方法的,源文件保留,不写进Doc的注解。

EventBus的Subscribe也是注解,定义如下

image

代表的意思这是一个写入doc,运行时保留,描述方法,不可继承的注解。

----------------------------1.元素之力------------------------

元素@Documented 是否会保存到 Javadoc 文档中,默认否(就是不写)。

元素@Retention 保留时间,默认为 CLASS。

作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)

取值(RetentionPolicy)有:

1.SOURCE:在源文件中有效(即源文件保留),SOURCE 大都为 Mark Annotation,这类 Annotation 大都用来校验,比如 Override, Suppress Warnings;

2.CLASS:在class文件中有效(即class保留);

3.RUNTIME:在运行时有效(即运行时保留)。

@Target 可以用来修饰哪些程序元素,默认未标注,表示可修饰所有。

作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

取值(ElementType)有:

1.CONSTRUCTOR:用于描述构造器;

2.FIELD:用于描述域;

3.LOCAL_VARIABLE:用于描述局部变量;

4.METHOD:用于描述方法;

5.PACKAGE:用于描述包;

6.PARAMETER:用于描述参数;

7.TYPE:用于描述类、接口(包括注解类型) 或enum声明。

@Inherited 是否可以被继承,默认为 false。

当一个 @Inherited类型标注的注解的Retention取值是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。

如果我们使用java.lang.reflect去查询一个@Inherited类型的注解,反射代码检查将展开如下工作:检查class和其父类,直到发现指定的注解类型被发现,或者到达类继承结构的顶层。

--------------------2.法术名------------

@interface修饰的就是注解的名称。

----------------------3.附魔环境-------------------------------

public @interface 注解名 {定义体}

在定义体里写方法名,实际上定义体内的方法名是注解的参数名。

定义体的返回值支持

1.所有基本数据类型(int,float,boolean,byte,double,char,long,short);

2.String类型;

3.Class类型;

4.enum类型;

5.Annotation类型;

6.以上所有类型的一维数组。

定义public@燃烧效果

{ int 火元素 default 500°;助燃体Class default 氢气;enum 氧气}

---------------------------4.释放技能------------------------------

image

在满足runtime,method时,

对handleEvent方法附上了一个优先级为0,粘性的subscribe魔法效果。

---------------------------------5.技能效果--------------------------

为什么要给方法加上注解呢?---为什么要给武器附魔呢?

答案很简单嘛,调用更快---武器更强。

参考
老司机教你 “飙” EventBus 3
https://segmentfault.com/a/1190000005089229?utm_source=tuicool&utm_medium=referral

EventBus使用详解(二)——EventBus使用进阶
http://blog.csdn.net/harvic880925/article/details/40787203

EventBus 3.1.1 源码解析
https://www.jianshu.com/p/89ee7dcbaca9

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • 文章基于EventBus 3.0讲解。首先对于EventBus的使用上,大多数人还是比较熟悉的。如果你还每次烦于使...
    Hohohong阅读 2,270评论 0 6
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,469评论 25 707
  • 对于Android开发老司机来说肯定不会陌生,它是一个基于观察者模式的事件发布/订阅框架,开发者可以通过极少的代码...
    飞扬小米阅读 1,468评论 0 50
  • 今天是特种兵训练的第三阶段――成交(入洞房)哈哈!老师给我们梳理了成交的注意事项和细节化的知识点!听了三遍我才明白...
    付爱宝二妞阅读 149评论 0 0
  • 在数学教育的旅途中,我甘愿做一个行者,不断行走、不断思考。幼苗需要土壤的滋养,孩子需要教师的爱护。尊重儿童,不要急...
    朱晓杰阅读 187评论 0 0