基于Agera的EventBus实现库

AgeraBus简介 AgeraBus 是基于谷歌开源的Agera实现的Android事件总线,实现了EventBus基本常用的功能,下面将为你一一介绍,如果要了解Agera,可以去看我文章后面推荐的两个地址。
添加依赖 在项目根目录的build.gradle中添加:

dependencies { compile 'xyz.zpayh:agerabus:1.0.4' compile 'com.google.android.agera:agera:1.3.0' }

基本用法 一个事件总线的使用总是少不了订阅、取消、发送事件,还有获取数据,下面我们来看下AgeraBus的基本用法,首先我们定义一个普通的类充当一个事件类型:
public class User{private String mName; public User(String name){ this.mName = name; }public void setName(String name){ this.mName = name; }public String getName(){ return this.mName; } }

简单的订阅,注销事件以及获取最新数据:
public class BaseActivity extends Activity implements Updatable{...@Override protected void onStart() { super.onStart(); //register 同一个Updatable实例只能订阅同一种事件类型一次,如需重新 //订阅,要先取消订阅,如果多次订阅会抛出异常,这里Activity实现了Updatable接口 AgeraBus.getDefault() .addUpdatable(this,User.class); }@Override protected void onStop() { super.onStop(); // unregister 取消订阅时,这个Updatable实例必须已经订阅了此事件, // 如果取消没有订阅的Updatable,会抛出异常 AgeraBus.getDefault() .removeUpdatable(this,User.class); }/** * 接收到事件时调用的接口 * */ @Override public void update() { // accept AgeraBus.getDefault()//获取默认总线 .getSupplier(User.class)//拿到数据提供者 .get()//获取封装好的数据Result .ifSucceededSendTo(new Receiver() {//数据成功接收到就发送给接收者 @Override public void accept(@NonNull User value) { //打印吐司 Toast.makeText(BaseActivity.this, value.getName(), Toast.LENGTH_SHORT).show(); } }); } }

上面就是最基本的订阅、取消事件以及接收数据。至于发送事件的话,只有一个入口:
AgeraBus.getDefault().post(new User("Sherlock"));

上面就是AgeraBus最基本的用法,下面简单讲解一下,
Agera 使用 push event, pull data 模型(推送事件,拉取数据)。 push event:被观察者只做事件通知,不携带任何数据; pull data:观察者根据自己需要从数据仓库(Repository.get())拉取数据。
由于push event, pull data模型是数据和事件通知分离的,所以上面看到的Updatable接口设计上并没有携带数据过来的,我们在update方法里,如果要拉取数据,可以从AgeraBus拿到订阅事件的数据提供者:
Supplier,再从Supplier中获取数据。
进阶用法 EventBus 提供了线程分发,订阅优先级,取消事件分发,粘性事件,而这些在AgeraBus也都一一实现了。
使用这些高级功能时,我们的订阅方法是使用另外一个接口。下面会介绍到。
线程分发与线程模型
ThreadMode有四种:
PostThread,MainThread,BackgroundThread,Async.
  • PostThread 订阅者将会被调用在与发布线程同样的线程中。上面基本用法就是采取这样的线程分发的,不涉及线程切换,通常是四种模式开销最小的一个。对于简单任务来说这是推荐用法,但使用这个分发模型要小心不要在主线程执行耗时长的任务,避免阻塞主线程。
  • MainThread 订阅者将会被回调在Android的Main线程中,适用于更新UI而又不无法确定事件来源于哪个线程的情况。
  • BackgroundThread 订阅者将在后台线程被回调,如果发布线程本身不是主线程,那么行为就跟PostThread一致,如果是在主线程发布事件,会切换到后台线程执行。
  • Async 订阅者总是在一个单独的线程被回调。
订阅优先级
你可以在注册订阅者的时候设置优先级改变事件分发的顺序,按优先级从高到低分发事件回调。
取消事件分发
你可以在接收事件,拿到数据value之后中断之后的事件分发:
AgeraBus.getDefault().cancel(value);

value 是从Supplier拿到的事件的数据,在update中调用上面的取消分发,后续的订阅者将不会接收到此次事件。
粘性事件
Agera 的 push event, pull data模型天然就是支持粘性事件,它总会保存最近(最新)的值,这样订阅粘性事件总是可以拿到最近(如果有)的数据。
使用方法
要使用上面这些高级功能,我们用AgeraBus另外一个接口方法订阅事件:
AgeraBus.getDefault() .compiler(User.class)//设置订阅事件的类型 .priority(priority)//设置优先级,或者调用.noPriority()不设置优先级(即为默认0优先级) .sticky()//设置为接收粘性事件,或者调用.noSticky()设置为不接收粘性事件(默认不接收粘性事件) .background()//设置分发线程,有background(),main(),posting(),async()对应四个分发模式(默认为posting模式) .compile(updatable); //设置订阅者,完成订阅

订阅事件不要中断链式调用,最后一定要调用compile(Updatable)完成调用
基本用法中的:
AgeraBus.getDefault() .addUpdatable(this,User.class);

就是全部设置了默认的方式(0优先级,不接收粘性事件,posting线程分发)。
注意 在不同线程分发时候拿到的数据,不一定是引发这次事件的数据,拿到的数据有可能要比引发事件的数据要新,在Agera Wiki 中文版中有说到,这是因为:
【基于Agera的EventBus实现库】由于 push event, pull data 模型和多线程情况下,观察者可能看不到数据全部的更新记录。 这是特意设计的: 因为大多数情况下(尤其更新app UI), 本来就只需要关心最新的数据。
上面的使用方法可以参考我的这个项目地址 AgeraBus,里面有使用Demo。可以看下AgeraBus的具体实现,由于本人技术水平有限,如有Bug,欢迎讨论。
参考文章 zjutkz的要做一个有冒险精神的人!开启漫漫的agera之旅
Agera Wiki 中文版

    推荐阅读