Android应用篇 - 观察者、EventBus、本地广播的区别

这篇文章来分析下观察者、EventBus 和本地广播的区别。评价某种方式优劣,有很多种指标,包括空间、时间等性能因素,还有代码的复杂程度,同整个程序的相性等等。

 

目录:

  1. 本地广播
  2. EventBus
  3. 观察者

 

 

1. 本地广播

优点:

  • 一般认为本地广播是三种方式中消耗时间、空间最多的一种方式,但也是同 Android 相对最好的方式。因为广播属于 Android 四大组件之一,在 BroadcastReceiver 中的 onReceive() 方法中可以获得 Context、Intent 参数。持有这两个参数便可以调用许多 Android sdk 中的方法,这一优势另外两种方式很难弥补的,无论是 EventBus 还是观察者,需要获得 Context 的话,往往都需要进行复杂的参数传递或者是依赖注入。
  • 本地广播另外的一个优点是,许多系统级的事件都是使用广播来进行通知的,像常用的电量变化、网络状态变化、短信发送接收的状态等等。这就使得与 Android 系统相关的通知,广播往往成了唯一的选择。

缺点:

  • 但这并不意味着 Android 系统中的通知都应该使用广播,因为相对于其它的方式而言,广播是重量级的、消耗资源较多的方式。广播的优势体现在它与 Android sdk 连接的更紧密,当我们需要同 Android 交互的时候,广播提供的便捷性抵消掉了它过多的资源消耗。但是对于不需要同 Android 交互或是只做很少的交互的时候,使用广播往往是一种浪费。
  • 并且在广播中有一个常见的坑:错误的使用 BroadcastReceiver 的 Context。在 Android 的 Application、Activity、Service、ContentProvider、BroadcastReceiver 中都可以获得对应的 Context,但它们并不完全相同。Activity 的 Context 所能做的事是最全的,而其它组件中的 Context 都或多或少的有着功能残缺。就拿常见的弹出 Dialog 来说,不知道有多少新手试图使用非 Activity 的 Context 创建 Dialog 最终无功而返。另外,使用 BroadcastReceiver 等非 Activity 组件的 Context启动 Activity 也有可能造成隐蔽的错误:当使用非 Activity 组件的 Context 启动 Activity 时,如果不指定 flag 的话,默认会创建一个新的 task,而使用 Activity 的 Context 并且不指定 flag 的话,默认会使用原 task。

 

 

2. EventBus

EventBus 作为 Android 开发中常用的框架,拥有着许多优点:

  • 调度灵活,不依赖于 Context,使用时无需像广播一样关注 Context 的注入与传递。
  • 父类对于通知的监听和处理可以继承给子类,这对于简化代码至关重要。
  • 通知的优先级,能够保证 Subscriber 关注最重要的通知。
  • 粘滞事件 (sticky events) 能够保证通知不会因 Subscriber 的不在场而忽略。

可继承、优先级、粘滞,是 EventBus 比之于广播、观察者等方式最大的优点,它们使得创建结构良好组织紧密的通知系统成为可能。使用简单。EventBus 的 Subscriber 注册非常简单,调用 EventBus 对象的 register() 方法即可,如果不想创建 EventBus 还可以直接调用静态方法 EventBus.getDefault() 获取默认实例,Subscriber 接收到通知之后的操作放在 onEvent 方法里就行了。成为 Publisher 的过程就更简单了,只需要调用合适的 EventBus (自己创建的或是默认的) 的 post 方法即可,快速且轻量。

EventBus 的缺点主要集中在它现阶段的实现方式,2.4.0 版是利用反射来实现的,后来改成 APT 实现。在 Subscriber 注册的时候,Subscriber 中的方法会被遍历查找以 onEvent 开头的 public 方法。这将带来一些问题,一旦对代码进行混淆,就无法查找到了,所以一个程序用到了 EventBus 又需要进行代码混淆时,就得设置混淆规则:

     -keepclassmembers class ** {
         public void onEvent*(**);
     }

     # Only required if you use AsyncExecutor
     -keepclassmembers class * extends de.greenrobot.event.util.ThrowableFailureEvent {
         <init>(java.lang.Throwable);
     }

但这种处理方式,对于保密度要求高的程序而言也是不可接受的,因为这暴露了方法名,给逆向留下了口子。好消息是 EventBus 已经打算使用注解来实现,这应该能够解决代码混淆的问题。

 

 

3. 观察者

 观察者这种设计模式应当属于程序员的基本功,由于观察者的实现比较简单,因此性能上是三者中最好的,但观察者难以控制通知的优先度,特别是一开始没有考虑优先度中途更改需求又加入优先度。另外观察者模式要求观察者在事件发生时在场才能收到通知,这就使得观察者有可能遗漏事件,一般来说这并不是问题,但是当程序要求观察者不能遗漏事件时那就坑了。客观来说,这并不能算作观察者的缺点,因为其它的方式往往也是这样,更加严谨的说法是观察者没有 EventBus 优先级、粘滞事件的优点。但有一个缺点是观察者独有的,那就是观察者可能会造成接口的膨胀。特别是当程序要求大量形式各异的通知,而程序员有没有做出良好的抽象时,代码中会包含大量的接口,接口数量的增长又会带来命名、注释等等一大堆问题。本质上说观察者要求程序员从零开始实现事件的产生、分发与处理过程,这就要求参与者必须对整个通知过程有着良好的理解。当程序代码适量时,这是一个合理的要求,然而当程序太大时,这将成为一种负担。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
EventBusAndroid 开发中一款非常实用的事件发布/订阅框架,它可以帮助开发者更方便地进行组件间通信,减少代码耦合度,提高代码复用性。在使用 EventBus 过程中,回调函数是非常重要的组成部分,下面我们来一起学习一下如何使用 EventBus 进行回调。 首先,在使用 EventBus 进行回调之前,需要先进行 EventBus 的注册和注销操作。在 Activity 或 Fragment 中注册 EventBus 的代码如下: ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 注册 EventBus EventBus.getDefault().register(this); } ``` 在 Activity 或 Fragment 销毁时,需要进行注销操作,代码如下: ```java @Override protected void onDestroy() { super.onDestroy(); // 注销 EventBus EventBus.getDefault().unregister(this); } ``` 接下来,我们来看一下如何使用 EventBus 进行回调。假设我们有一个 Activity A,需要从另一个 Activity B 中获取数据并进行处理,在 Activity A 中,我们可以定义一个事件,如下: ```java public class DataEvent { private String data; public DataEvent(String data) { this.data = data; } public String getData() { return data; } } ``` 在 Activity B 中,我们可以通过 EventBus 发送该事件,并传递数据,如下: ```java EventBus.getDefault().post(new DataEvent("Hello EventBus!")); ``` 在 Activity A 中,我们需要定义一个方法来接收该事件,并进行相应的处理,代码如下: ```java @Subscribe(threadMode = ThreadMode.MAIN) public void onDataEvent(DataEvent event) { String data = event.getData(); // 处理数据 } ``` 在这个方法上使用了 @Subscribe 注解,表示该方法用来接收事件,threadMode = ThreadMode.MAIN 表示该方法在主线程中执行。当 Activity A 接收到事件后,该方法就会被调用,并将事件中传递的数据作为参数传递给该方法。这样,我们就实现了通过 EventBus 进行回调的功能。 需要注意的是,使用 EventBus 进行回调时,需要保证订阅者和发布者在同一进程中,否则无法接收到事件。另外,在使用 EventBus 进行回调时,建议使用事件模型,将数据封装成事件对象,这样可以更好地进行解耦和管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值