EventBus 3使用文档(四)

异步执行器(AsyncExecutor)

异步执行器就像是线程池,但是包含了失败后的异常处理。失败时会抛出异常,这些异常会被异步执行器捕捉并且包装到事件里面,最后把事件发送出去。

申明:AsyncExecutor是一个非核心工具类。它可以帮你减少一些在后台线程上发生的异常处理,但是它不是核心的EventBus类。

通常,你通过调用AsyncExecutor.create()来创建一个实例并且在Application作用域保存。之后,如果需要执行某个操作,只需实现RunnableEx接口并且传入AsyncExector的execute方法。与Runnable不同的是,RunnableEx可能会抛出异常。

如果RunnableEx抛出了异常,这个异常会被AsyncExecutor捕捉并且包装进ThrowableFailureEvent当中,并且发送出去。

运行的例子:

AsyncExecutor.create().execute(
    new AsyncExecutor.RunnableEx() {
        @Override
        public void run() throws LoginException {
            // No need to catch any Exception (here: LoginException)
            remote.login();
            EventBus.getDefault().postSticky(new LoggedInEvent());
        }
    }
);

例子的接收事件部分:

@Subscribe(threadMode = ThreadMode.MAIN)
public void handleLoginEvent(LoggedInEvent event) {
    // do something
}

@Subscribe(threadMode = ThreadMode.MAIN)
public void handleFailureEvent(ThrowableFailureEvent event) {
    // do something
}

异步执行器Builder(AsyncExecutor Builder)

如果想自定义AsyncExecutor实例,你可以调用静态方法AsyncExecutor.builder()。它会返回一个builder,允许你自定义EventBus实例、线程池、失败事件的类。

另一个自定义选项是运行范围(execution scope),这会提供失败事件的上下文信息。举例来说,一个失败事件只会关联到一个特定的Activity实例或类。

如果你的自定义失败事件类实现了HasExecutionScope接口,AsyncExecutor会自动设置运行环境上下文。这样一来,你的订阅者就能查到失败事件的上下文,然后根据上下文进行相应的处理。

EventBus常见问题和异常解决

常见问题

EventBus是一种软件架构吗?

不,它本身不是。EventBus可以帮助解决一些架构问题,比如组件之间的解耦。但你仍然需要自己设计想要的app架构。大多数时候,会把你的app分成很多层(比如,UI层,逻辑层,数据获取层),这有助于分解和解决app的复杂性问题。根据开发者的不同喜好,EventBus可以出现在任何你想要的分层(EventBus关心的是切片,译者注:不了解切片的,可以搜索AOP),也可以严格地只在同一层传递(但这可能会需要多次重复发送事件,这是十分不便的)。始终记得:不要过度使用EventBus,你可以直接调用方法。

EventBus与Android的广播机制有什么不同

与Android的广播机制不同,EventBus使用标准Java类作为事件并且提供了更多便捷的API。EventBus会有更多的使用场景,而你也不再需要经历繁杂的Intent设置,填充Intent的Extras,实现广播接收者然后再把数据从Intent Extras中提取出来。同时,使用EventBus传递事件开销要小得多。

异常解决

当我发送一个事件时,会接收到两次或多次事件。但是我只有一个订阅方法。为什么会导致这个问题?

检查你是否有多个订阅者类的实例被同时注册到了EventBus。典型的场景有:1)忘记调用unregister;2)某个Fragment多次attach到Activity。想要验证这些场景,只要在你注册和反注册的地方添加log:如果注册调用的次数大于反注册次数+1,就可以证明你的app没有正确的进行注册和反注册。

注册一个订阅者时抛出了java.lang.NoClassDefFoundError,我该怎么办?

首先介绍一些背景知识来帮助你理解为什么会发生这种情况:一些Android版本在调用getDeclaredMethodsgetMethods时似乎存在bug。当类中的某个方法包含了当前API level上不存在的类时会抛出异常。比如,PersistableBundle这个类是在API level 21时添加的。随之一起的,在Activity中添加了一些新的生命周期方法,其中就有使用PersistableBundle作为参数的方法,比如onCreate (Bundle savedInstanceState, PersistableBundle persistentState)。如果你覆写了这个方法,然后把它注册到EventBus,那么在旧版本的设备上,你就会引发之前描述的bug。知道了原理,就能轻松的解决这个问题了。

下面是关于修复这个问题的一些建议(按照顺序逐条检查):

  1. 也许你只是意外的覆写了带有PersistableBundle参数的生命周期方法。如果是这样,就换个不带PersistableBundle参数的方法,比如onCreate (Bundle savedInstanceState)
  2. 使用EventBus 3的订阅者索引。这可以避免反射,同样也避免了这个问题。甚至你还能因此获得一点好处,使得app启动时注册订阅者的速度大大增加。
  3. 从订阅者类中移除这些有问题的方法。把这些订阅方法移动到新的订阅者类中,或者把有问题的方法移到非订阅者类都可以。
  4. 如果有问题的方法是public的,将它改成非public。因为“B方案”的存在,这样也能避免bug:EventBus会先调用getDeclaredMethods,这会导致失败。接下来(译者注:捕捉到之前的失败后),EventBus会再次尝试使用getMethods(“B方案”)。后者会成功,因为后者只返回public方法。然而,这是从性能上来考虑最差的解决方案(2次反射调用,而不是1次,并且还有getMethods方法会将整个类的继承结构都考虑进去)。

为什么我会得到警告:“The following options were not recognized by any processor: ‘[eventBusIndex]’”?

这会发生在你设置好了build脚本,但是还没有在代码中添加任何的注解(译者注:当然是指EventBus自己的注解)。因为没有任何的@Subscribe注解,注解处理器也就不会被执行,所以也就无法去使用’eventBusIndex’选项了。所以,只要加上一些@Subscribe注解就不会有这个问题了。

译者的一些额外说明

  1. 订阅方法,也就是想要加上@Subscribe注解的方法,无论你是否启用订阅者索引,都需要将该方法声明成public。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
EventBus是一个轻量级的事件发布/订阅库,可以方便地实现组件之间的通信。它可以大大简化应用程序中的消息传递,减少了代码的耦合度,从而提高了应用程序的可维护性和可扩展性。 使用EventBus,你需要在你的项目中添加EventBus库的依赖。在gradle配置文件中添加如下代码: ```groovy dependencies { implementation 'org.greenrobot:eventbus:3.2.0' } ``` 然后,你需要定义你的事件类,例如: ```java public class MessageEvent { public final String message; public MessageEvent(String message) { this.message = message; } } ``` 接下来,订阅者需要在其onCreate()方法中注册到EventBus中: ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EventBus.getDefault().register(this); } ``` 然后,你可以在订阅者中定义事件处理方法: ```java @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) { Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show(); } ``` 最后,当你想要发送一个事件时,你可以使用EventBus的post()方法: ```java EventBus.getDefault().post(new MessageEvent("Hello world!")); ``` 这个事件将被所有订阅者接收,并且可以在onMessageEvent()方法中处理。需要注意的是,当你不再需要接收事件时,你需要在onDestroy()方法中注销订阅者: ```java @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } ``` 这就是使用EventBus的基本方法。当然,EventBus还有很多高级用法,比如可以指定事件的优先级、自定义线程模式等等。你可以查看官方文档来了解更多信息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值