Android事件总线框架之EventBus(3.0为例)

实际项目开发过程中,经常遇到如下场景:不同的应用程序组件的控件间具有一定的相互关联性,其中用户对后者进行的某种操作会引起前者的相应改变。举一个具体的场景:以新浪微博为例,在新浪微博首页好友动态列表页和好友动态详情页(微博正文),对于每个详情页而言,布局基本一致,在详情页点击了个赞,赞的数量增加,同时赞的图标发生了变化,此时返回到列表页,此新浪微博首页上的赞图标以及数量与刚刚详情页的需要保持一致。再举一个例子,对于多个底部导航tab下的资讯类阅读app,在咨询详情页点击了收藏,然后收藏成功,此时回到底部tab中的个人中心,假如个人中心中有我的收藏,同时后面显示的是收藏数量,此时此收藏数量需要同于于刚刚用户所进行的收藏/取消收藏而即时更改数字。显而易见,类似场景需求非常常见。

有时候,当此类需求相对简单时,通过接口以实现回调等方式可以完成,但是当不同组件/控件之间的关系纷繁复杂时,基于接口的方案不仅使得代码非常繁琐,同时是的程序逻辑很混乱,基于此,Android事件总线框架(AndroidEventBus 、EventBus、Otto) ,为此类需求的实现提供了非常方便的方案。

这里我以EventBus框架为例,为大家实现该功能。


什么是EventBus?

EventBus是Android下高效的发布/订阅事件总线机制。作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment,Activity,Service,线程之间传递数据,执行方法。特点是代码简洁,是一种发布订阅设计模式(Publish/Subsribe),或称作观察者设计模式。事件传递既可用于 Android 四大组件间通讯,也可以用户异步线程和主线程间通讯等等。传统的事件传递方式包括:Handler、BroadCastReceiver、Interface 回调,相比之下 EventBus 的优点是代码简洁,使用简单,并将事件发布和订阅充分解耦。

EventBus框架 基本结构


EventBus 负责存储订阅者、事件相关信息,订阅者和发布者都只和 EventBus 关联。

EventBus作为一个消息总线,有三个主要的元素:

  • Event:事件。可以是任意类型的对象
  • Subscriber:事件订阅者,接收特定的事件。在EventBus中,使用约定来指定事件订阅者以简化使用。即所有事件订阅都都是以onEvent开头的函数,具体来说,函数的名字是onEvent,onEventMainThread,onEventBackgroundThread,onEventAsync这四个,这个和 
    ThreadMode(下面讲)有关。
  • Publisher:事件发布者,用于通知 Subscriber 有事件发生。可以在任意线程任意位置发送事件,直接调用eventBus.post(Object) 方法,可以自己实例化 EventBus 
    对象,但一般使用默认的单例就好了:EventBus.getDefault(), 根据post函数参数的类型,会自动调用订阅相应类型事件的函数。


事件响应流程图

订阅者首先调用 EventBus 的 register 接口订阅某种类型的事件,当发布者通过 post 接口发布该类型的事件时,EventBus 执行调用者的事件响应函数。


EventBus使用详解

EventBus使用步骤

1.引入EventBus:
引入eventbus:3.0.0

  compile 'org.greenrobot:eventbus:3.0.0'
2.构造发送消息类

注册号事件订阅者之后,第二步就是构造发送消息类,这个类就是我们要发送的对象,所以这个类怎么写都行,只要你把要传递的东西能够存进这个对象中又能够从这个对象中拿出来就好。OK,我写了一个简单的消息类,如下:

public class MainMessage {
    private String msg;

    public MainMessage(String msg) {
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }
}

3.注册事件订阅者
使用EventBus我们首先要注册事件订阅者,这个事件订阅者就是说我们订阅的事件一会要在哪里进行处理,事件订阅者的注册和广播注册非常相似,有注册,也有解除注册,一般情况下,我们在Activity的onCreate()方法中进行注册,在Activity的onDestory()方法中解除注册。OK,代码如下:

注册:
EventBus.getDefault().register(this);
解除注册:
EventBus.getDefault().unregister(this);
所以完整的代码应该是这个样子:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

4.发送事件:即发送消息
EventBus.getDefault().post(messageEvent);

5.处理消息
在3.0之前,EventBus还没有使用注解方式。消息处理的方法也只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,分别代表四种线程模型。而在3.0之后,消息处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(beta1默认为PostThread,正式版默认为POSTING),四种线程模型,下面会讲到。 
注意,事件处理函数的访问权限必须为public,否则会报异常。

以3.0版为例
  @Subscribe(threadMode = ThreadMode.POSTING) //3.0.0
    public void onMessageEventPost(UserEvent event) {
    //默认方式, 在发送线程执行
    }

 @Subscribe(threadMode = ThreadMode.MAIN) 
    public void onMessageEventMain(UserEvent event) {
    //在ui线程执行
    }

   @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onMessageEventBackground(UserEvent event) {
     //在后台线程执行
    }

 @Subscribe(threadMode = ThreadMode.ASYNC) 
    public void onMessageEventAsync(UserEvent event) {
    //强制在后台执行
    }

注意:ThreadMode.BackgroundThread和ThreadMode.Async的不同之处是前者发送方在主线程而接收方就会在后台线程处理消息,但如果发送方在一个子线程,那么接收方和发送方在同一个线程处理消息,后者则强制接收方在后台线程处理消息,不管发送方在哪个线程,但消息的处理都是异步的,如果后台进程被阻塞,那么就会开例外一个后台线程,否则都在一个后台线程中处理消息。


6.代码混淆
 -keepclassmembers class ** {
    public void onEvent*(**);
    void onEvent*(**);
 }

注意:

@Subscribe 下的方法必须为public
postSticky()发送的粘性消息订阅时必须@Subscribe(sticky = true)否则接收不到
发送的event事件是object类
@Subscribe(priority = 1) 使用时优先级默认为0,然后只有统一模式下设置优先级才有效果,自己看着合理使用


EventBus demo下载




参考资料:








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值