Android 中 EventBus 的使用之多线程事件处理

在这一系列教程的最后一篇中,我想谈谈GR的EventBus,在处理多线程异步任务时是多么简单而有效。

AsyncTask, Loader和Executor…… 拜托!

Android中有很多种执行异步操作的方法(指平行于UI线程的)。AsyncTask对于用户来说是最简单的一种机制,并且只需要少量的设置代码即可。然而,它的使用是有局限的,正如Android官方文档中所描述的:

AsyncTask被设计成为一个工具类,在它内部包含了Thread和Handler,但它本身并不是通用线程框架的一部分。AsyncTask应该尽可能地被用在执行一些较短的操作中(最多几秒)。如果你需要在线程中执行较长时间的任务,那么建议你直接使用java.util.concurrent包中提供的各种API,如Executor、 ThreadPoolExecutor以及FutureTask。

不过即便是执行短时间的操作也会带来一些问题,特别是在与Activity/Fragment生命周期有关的地方。由于AsyncTask会持续地运行下去(即使启动它们的Activity/Fragment已经被销毁了)。这样,一旦你在onPostExecute方法中试图对UI进行更新,那么最终将导致抛出一个IllegalStateException异常。

Android 3.0中引入了Loader API用来解决Activity/Fragment生命周期的问题(它们的确很有效)。Loader API被设计成向Activity/Fragment中以异步方式加载数据。尽管加载数据是一种非常常见的异步操作,但并非唯一一种需要从UI线程中分开的操作。Loader还需要在Activity/Fragment中实现另外一个监听接口。尽管这么做没有错,但我个人并不喜欢这种模式(我的意思是最终你的代码中会包含许多的回调函数,导致代码的可读性变得很差)。最后,Activity和Fragment也并非唯一需要对异步操作分线程的地方。例如如果在Service里,你就不能访问LoaderManager,所以最终你还是得使用AsyncTask或者java.util.concurrent。

java.util.concurrent包很不错,我在Android和非Android项目中都可以使用。不过使用时需要对其进行多一点儿配置和管理,不象AsyncTask那么简单。你需要对ExecutorService进行初始化,管理和监视它的生命周期,并且可能需要跟一些Future对象打交道。

只要使用恰当,AsyncTask、 Loader和Executor都是非常有效的。但在复杂应用中,需要为每个任务选择合适的工具,最终你可能三种都会用到。这样你就得维护三种不同的处理并发的框架代码。

Green Robot来帮忙了!

GR的EventBus中内置了一个非常棒的并发处理机制。在监听类中,你可以实现4种不同类型的处理方法。当一个匹配事件被发送过来时,EventBus会根据不同的并发模型将事件发送到相应的处理方法中:

onEvent(T event):运行在和被发送事件相同的线程中。
onEventMainThread(T event):运行在主(UI)线程中,不管事件从哪个线程中被发送过来。
onEventAsync(T event):运行在单独的线程中,即非UI线程,也非发送事件的线程。
onEventBackgroundThread(T event):如果发送事件的线程不是UI线程,则运行在该线程中。如果发送事件的是UI线程,则它运行在由EventBus维护的一个单独的线程中。多个事件会同步地被这个单独的后台线程所处理。

这些方法功能强大而且使用简单。例如有一个比较耗时的操作(可能是网络调用,大量数据处理等),这一操作需要由UI上的行为来触发,并且当操作执行完毕后还需对UI进行更新。在这个例子中,UI行为即按钮点击,按钮在activity中,耗时操作在service中。我们可以按下面的方式来实现:

Java

尽管这个例子比较简单,但它却非常简明扼要地说明了问题。这里即不需要实现监听接口,也不会出现类似生命周期之类的问题(由于activity只能在它存在的时候才能接收到OperationCompleteEvent事件)。除此之外,如果发生了配置改变(旋转屏幕)或其他什么原因导致activity在两次事件发生之间被销毁并重建,最终仍可以接收到OperationCompleteEvent事件。

此外,我们也可以容易地想到一些其它用法。比如,如果需要将更新进度发出去,你只需另外实现一个封装了进度值的事件类,然后将其发送出去即可。或者,如果你想让其它一些事件(不管是相同还是不同类型)不被并行处理(同步执行),你可以选择使用onEventBackgroundThread。

依赖Bus

实例化EventBus最简单的方法就是通过EventBus.getDefault()。然而,在EventBusBuilder类(通过EventBus.builder()获得)中还包含了另外一些有用的配置方法。特别是在本文中提到过的使用你自己的ExecutorService。缺省情况下EventBus通过Executors.newCachedThreadPool()创建自己的ExecutorService,在大多数情况下都已满足你的需要。然而,有时你可能仍然想要显示地控制EventBus所使用的线程数量,这种情况下你就可以象下面这样初始化EventBus:

Java

EventBus.builder().executorService(Executors.newFixedTheadPool(NUM_THREADS)).installDefaultEventBus();

在EventBusBuilder中另外一些可供配置的是一些和异常处理的有关的控制,以及一个是否允许事件类被继承的控制开关。这些内容超出了本文所讨论的范围,但我还是建议你仔细去研究一番。GR可能并没有把这些内容都写在文档里,但如果你读一读EventBusBuilder和EventBus的源代码,相信你会很容易理解它们的。

(0)

相关推荐

  • Android之利用EventBus发送消息传递示例

    一.概述 EventBus是一款针对Android优化的发布/订阅事件总线.主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅.以及将发送者和接收者解耦. 1.下载EventBus的类库 源码:EventBus_jb51.rar 2.基本使用 (1)自定义一个类,可以是空类,比如: public class AnyEventType { public AnyEventType(){} }

  • Android中使用开源框架eventbus3.0实现fragment之间的通信交互

    1.概述 在之前的博文中简单介绍过如何实现fragment之间的信息交互:<Android中Fragment与Activity之间的交互(两种实现方式)>,今天继续给大家介绍一种可以实现此效果的另外一种方式EventBus.(相比于handler,接口回调,bundle传参,这个简单好用到哭) EventBus是Android下高效的发布/订阅事件的消息总线.作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment.Activity.Service.线程

  • Android EventBus 3.0.0 使用总结(必看篇)

    前言 EventBus框架 EventBus是一个通用的叫法,例如Google出品的Guava,Guava是一个庞大的库,EventBus只是它附带的一个小功能,因此实际项目中使用并不多.用的最多的是greenrobot/EventBus,这个库的优点是接口简洁,集成方便,但是限定了方法名,不支持注解.另一个库square/otto修改自 Guava ,用的人也不少.所以今天我们研究的目标是greenrobot的EventBus. EventBus 简介 1.EventBus3.0.0 是最新的

  • Android 消息分发使用EventBus的实例详解

    Android 消息分发使用EventBus的实例详解 1. AndroidStudio使用 dependencies { //最新版本 compile 'org.greenrobot:eventbus:3.0.0' //可以翻倍提高EventBus使用效率 provided 'de.greenrobot:eventbus-annotation-processor:3.0.0-beta1' } 2. 在基类Activity中配置 /** * Activity基类 */ protected Eve

  • Android 中 EventBus 的使用之多线程事件处理

    在这一系列教程的最后一篇中,我想谈谈GR的EventBus,在处理多线程异步任务时是多么简单而有效. AsyncTask, Loader和Executor-- 拜托! Android中有很多种执行异步操作的方法(指平行于UI线程的).AsyncTask对于用户来说是最简单的一种机制,并且只需要少量的设置代码即可.然而,它的使用是有局限的,正如Android官方文档中所描述的: AsyncTask被设计成为一个工具类,在它内部包含了Thread和Handler,但它本身并不是通用线程框架的一部分.

  • Android实现EventBus登录界面与传值(粘性事件)

    本文实例为大家分享了Android实现EventBus登录界面与传值的具体代码,供大家参考,具体内容如下 展示效果 添加EventBus导入依赖 compile 'org.greenrobot:eventbus:3.0.0' 主MainActivity方法 public class MainActivity extends AppCompatActivity { private EditText username,password; private Button btn_go; private

  • 浅谈Android中多线程切换的几种方法

    我们知道,多线程是Android开发中必现的场景,很多原生API和开源项目都有多线程的内容,这里简单总结和探讨一下常见的多线程切换方式. 我们先回顾一下Java多线程的几个基础内容,然后再分析总结一些经典代码中对于线程切换的实现方式. 几点基础 多线程切换,大概可以切分为这样几个内容:如何开启多个线程,如何定义每个线程的任务,如何在线程之间互相通信. Thread Thread可以解决开启多个线程的问题. Thread是Java中实现多线程的线程类,每个Thread对象都可以启动一个新的线程,注

  • Android中实现多线程操作的几种方式

    目录 前言 最基础的方式 继承Thread类并实现run()方法 匿名内部类 实现Runnable接口 callable+FutureTask 线程池 手动创建线程池 使用Executors创建线程池 Android中特有的实现多线程 使用HandlerThread 使用IntentService JobIntentService/JobScheduler WorkManager WorkManager 使用协程 AsyncTask 结语 前言 多线程一直是一个老大难的问题,首先因为它难以理解,

  • Android中父View和子view的点击事件处理问题探讨

    android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解. 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP 当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底是ViewG

  • Android中Handler消息传递机制

    Handler 是用来干什么的? 1)执行计划任务,可以在预定的时间执行某些任务,可以模拟定时器 2)线程间通信.在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息.当你创建子线程时,你可以在你的子线程中拿到父线程中创建的Handler 对象,就可以通过该对象向父线程的消息队列发送消息了.由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面. 出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发

  • Android中单例模式的一些坑小结

    前言 单例模式最初的定义出现于<设计模式>(艾迪生维斯理, 1994):"保证一个类仅有一个实例,并提供一个访问它的全局访问点." 而我对单例的理解是,在可控的范围内充当全局变量的作用,就相当于C语言中一个全局结构体. 首先来看这样一个单例,稍微有点经验的同学可能都会说,这样的单例是非线程安全的.要加个volatile关键字才可以. class Singleton{ private static Singleton singleton; private Singleton(

  • Android中的二维码生成与扫描功能

    0. 前言 今天这篇文章主要描述二维码的生成与扫描,使用目前流行的Zxing,为什么要讲二维码,因为二维码太普遍了,随便一个Android APP都会有二维码扫描.本篇旨在帮助有需求的同学快速完成二维码生成和扫描的功能. 1.    Zxing的使用 从github上下载项目后,可以看到整体代码结构如下: 我们只需将Zxing包下的所有代码copy一份到我们的项目中去,除了这些还需要zxing的jar包,最后相应的资源文件,包括values文件下的ids文件.raw文件中的资源文件(可以替换).

  • 详解Android中解析XML的方法

    XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能.今天就由我向大家介绍一下在Android平台下几种常见的XML解析和创建的方法. 在Android中,常见的XML解析器分别为SAX解析器.DOM解析器和PULL解析器,下面,我将一一向大家详细介绍. SAX解析器: SAX(Simple API for XML)解析器是一种基于事件的解析器,它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的.当事

随机推荐