个人对EventBus和回调的一些思考

EventBus是近年来在Android开发中非常常用的一个通信框架,利用它可以很轻易地实现组件与组件之间的各种通信,无论跨线程与否。

而回调则是在Android开发中哪儿都能见到的编程逻辑,常见的onCreate()等生命周期方法以及OnXXXListener这些都是回调来的。

在EventBus出来之前(或许还有RxAndroid之类的,不过我还没使用过Rx系列,所以暂且不提),在Android开发中,组件间的通信或者前后端线程之间的通信都是通过持有引用的回调或者Handler来实现的。

使用回调有什么不好呢?

  1. 强引用,可能导致内存泄漏。
  2. 多层回调的代码逻辑可读性差,调试时甚至使人抓狂。
  3. 直接用匿名内部类去实现很容易就出现多级缩进,长长的屏幕都看不完一行代码。
  4. 要跨线程必须要用Handler。

而EventBus是可以替代回调的。但替代的时候并不是那么简单地在原来调用回调方法的地方调用EventBus的post方法即可。如果只是这样简单的替换,还是有可能产生你意料之外的状况的。

使用EventBus替代回调的时候,应当有以下步骤:

  1. 把回调里传的数据抽离成一个消息类Msg,一个回调方法对应一个消息类。
  2. 在调用回调方法的地方把调用改为EventBus的post方法,参数是上一步中抽取出来的Msg类。
  3. 把原来实现了的回调方法改为用Subscribe注解标明该在哪类线程运行,并把原参数改为抽取出来的Msg类,在具体实现里再从Msg实例取出对应的数据。
  4. 在添加回调的代码处改为EventBus的register方法;并在所处的组件销毁时的回调方法(如onDestroy、onDestroyView等,注意要和register方法所处的生命周期对称)内调用EventBus的unregister方法。

看样子似乎就这样做是没问题的。

但是,考虑一个情况,Fragment A 和 Fragment B都需要同一类消息Msg,然后从Fragment A里调用了耗时操作去请求Msg,在还没获得之前就退出了A进入到B,然后B又去请求,然后一直待在B那里的话,那么B就会收到两次Msg,一次是A请求的,一次是自己请求的,那么这时候B对消息Msg的处理逻辑就有可能出错,因为一般来说这种通信式的逻辑是非幂等的。

针对这种情形有两种解决方案:

  1. 持有耗时操作的引用,在调用EventBus的unregister方法时,同时调用耗时操作的取消方法。
  2. 在Msg内部再加一个id的属性来区别这个Msg的来源。

我建议是使用第一种解决方案,因为这个解决方案涉及的代码改动量是更少的。如果采用第二种解决方案的话,那你得在所有涉及到Msg这个类的构建修改的操作逻辑那里添加对id属性透传的逻辑,修改的代码越多越容易引入新问题

那加上这一步之后是不是就高枕无忧了呢?

不一定,EventBus是不支持post null的,那么之前在回调中,有使用到null来进行判断的逻辑就得改了,这是其一。第二点就是List、Map这类泛型类型是很不合适作为Msg类的,原因就是Java的类型擦除会把泛型对应的具体类型信息擦除掉,而EventBus却恰恰就是利用这个信息来进行消息分发的,两个都Subscribe了的方法,如果它们的接收参数都是List,即使一个是List<String>,一个是List<Integer>,EventBus在分发List类型的消息时是两个方法都会被调用的,这样如果不在方法内部再进行一次类型判断,很容易就会造成崩溃。

基于我最近的使用经历来看,如果真的按以上的做法来写好了,那确实EventBus是很好地替代了回调的功能。

那么EventBus有没有缺点呢?哈哈哈哈当然有啦。

  1. 只要用得一多,那消息类的数量必然是会爆炸性增长。
  2. 调试的时候除非熟悉整块逻辑,不然不跑起来你是没办法了解Subscribe的方法的数据来源。

说完两个的缺点,再说说优点。

回调的:

  1. 绝对的一一对应,非常精确。
  2. 使用回调可以使得逻辑的设计思路很清晰。

EventBus的:

  1. 松耦合。
  2. 使用简单。

以上就是我对EventBus和回调的使用思考。还是颇为浅显,日后若有更深的理解了再开一文。

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

推荐阅读更多精彩内容