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<User>
.ifSucceededSendTo(new Receiver<User>() {//数据成功接收到就发送给接收者
@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 中文版中有说到,这是因为:
由于 push event, pull data 模型和多线程情况下,观察者可能看不到数据全部的更新记录。 这是特意设计的: 因为大多数情况下(尤其更新app UI), 本来就只需要关心最新的数据。
上面的使用方法可以参考我的这个项目地址 AgeraBus,里面有使用Demo。可以看下AgeraBus的具体实现,由于本人技术水平有限,如有Bug,欢迎讨论。