AndroidEventBus(事件总线)了解+实战体验

转载请注明出处:http://blog.csdn.net/woshizisezise/article/details/51225186

大家好,今天咱们来说说本人最近使用到的一个新的开源工具类,也就是今天的主人公AndroidEventBus,叫做事件总线,刚开始看到这个名字的时候我以为就是之前使用到的EventBus,于是乎好奇的我就接着研究了一下,果然它是类似EventBus的消息处理机制,提供了更好的使用性,我便希望把它集成到我正在开发的工程里,因为工程较大以及代码较为繁琐,我不敢轻易的集成与使用,所以我先写了一个简单的例子验证这个框架的实用性,还是发现了一点点问题的,咱们慢慢来说。

(一)项目介绍

首先我们从Github项目官方网站上可以看到它的介绍,方便大家的阅读性,我打开了中文.README,这是一个Android平台的事件总线框架, 它简化了Activity、Fragment、Service等组件之间的交互,很大程度上降低了它们之间的耦合,使得我们的代码更加简洁,耦合性更低,提升我们的代码质量。AndroidEventBus吸收了greenrobot的EventBus以及square的otto的优点,并在此基础上做出了相应的改进,使得事件总线框架更适合用户的使用习惯,也使得事件的投递更加的精准、灵活。

确实,之前使用EventBus的时候有一个困扰的问题就是通过EventBus.getDefault.post()出去的消息,都是根据我们post方法里传递的对象类型去查找接收的方法,只要对象类型一致,那么EventBus负责消息处理的方法都会接收并处理消息,所以有时候我们不得不创建很多的对象仅仅是为了区分它们所要处理的对象,这一点肯定是不太好的,所以当看到这个框架的时候,文档中写上了通过Subscriber注解来标识事件接收对象中的接收方法,那么它就应该实现了精准定位的方式,只要我们指定一个tag(可以理解为事件消费类型),那么它就可以处理同一类事务,事实上它做到了,很棒。

(二)与greenrobot的EventBus的不同

  • 以下文字摘自官方文档作者语录

greenrobot的EventBus是一个非常流行的开源库,但是它在使用体验上并不友好,例如它的订阅函数必须以onEvent开头,并且如果需要指定该函数运行的线程则又要根据规则将函数名加上执行线程的模式名,这么说很难理解,比如我要将某个事件的接收函数执行在主线程,那么函数名必须为onEventMainThread。那如果我一个订阅者中有两个参数名相同,且都执行在主线程的接收函数呢?

这个时候似乎它就没法处理了。而且规定死了函数命名,那就不能很好的体现该函数的功能,也就是函数的自文档性。AndroidEventBus使用注解来标识接收函数,这样函数名不受限制,比如我可以把接收函数名写成updateUserInfo(Personinfo),这样就灵活得多了。

另一个不同就是AndroidEventBus增加了一个额外的tag来标识每个接收函数可接收的事件的tag,这类似于Broadcast中的action,比如每个Broadcast对应一个或者多个action,当你发广播时你得指定这个广播的action,然后对应的广播接收器才能收到.greenrobot的EventBus只是根据函数参数类型来标识这个函数是否可以接收某个事件,这样导致只要是参数类型相同,任何的事件它都可以接收到,这样的投递原则就很局限了。比如我有两个事件,一个添加用户的事件,一个删除用户的事件,他们的参数类型都为User,那么greenrobot的EventBus大概是这样的:

private void onEventMainThread(User aUser) {
    // code
}

如果你有两个同参数类型的接收函数,并且都要执行在主线程,那如何命名呢 ? 即使你有两个符合要求的函数吧,那么我实际上是添加用户的事件,但是由于EventBus只根据事件参数类型来判断接收函数,因此会导致两个函数都会被执行。AndroidEventBus的策略是为每个事件添加一个tag,参数类型和tag共同标识一个事件的唯一性,这样就确保了事件的精确投递。

(三)基本结构

AndroidEventBus类似于观察者模式,通过register函数将需要订阅事件的对象注册到事件总线中,然后根据@Subscriber注解来查找对象中的订阅方法,并且将这些订阅方法和订阅对象存储在map中。当用户在某个地方发布一个事件时,事件总线根据事件的参数类型和tag找到对应的订阅者对象,最后执行订阅者对象中的方法。这些订阅方法会执行在用户指定的线程模型中,比如mode=ThreadMode.ASYNC则表示该订阅方法执行在子线程中。

(四)集成与使用

  • jar文件集成

将jar文件添加到工程中的引用中即可,AndroidEventBus.jar下载

  • Android Studio集成

在Module的build.gradle添加依赖

dependencies {
    compile fileTree(dir: ‘libs‘, include: [‘*.jar‘])
    // 添加依赖
    compile ‘org.simple:androideventbus:1.0.5.1‘
}
  • 你可以按照下面几个步骤来使用AndroidEventBus。

1.注册事件接收对象

public class YourActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        // 注册对象
        EventBus.getDefault().register(this);
    }

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

2.通过Subscriber注解来标识事件接收对象中的接收方法

public class YourActivity extends Activity {

    // code ......

    // 接收方法,默认的tag,执行在UI线程
    @Subscriber
    private void updateUser(User user) {
        Log.e("", "### update user name = " + user.name);
    }

    // 含有my_tag,当用户post事件时,只有指定了"my_tag"的事件才会触发该函数,执行在UI线程
    @Subscriber(tag = "my_tag")
    private void updateUserWithTag(User user) {
        Log.e("", "### update user with my_tag, name = " + user.name);
    }

    // 含有my_tag,当用户post事件时,只有指定了"my_tag"的事件才会触发该函数,
    // post函数在哪个线程执行,该函数就执行在哪个线程
    @Subscriber(tag = "my_tag", mode=ThreadMode.POST)
    private void updateUserWithMode(User user) {
        Log.e("", "### update user with my_tag, name = " + user.name);
    }

    // 含有my_tag,当用户post事件时,只有指定了"my_tag"的事件才会触发该函数,执行在一个独立的线程
    @Subscriber(tag = "my_tag", mode = ThreadMode.ASYNC)
    private void updateUserAsync(User user) {
        Log.e("", "### update user async , name = " + user.name + ", thread name = " + Thread.currentThread().getName());
    }
}

User类大致如下 :

public class User  {
   String name ;
    public User(String aName) {
        name = aName ;
    }
}

接收函数使用tag来标识可接收的事件类型,与BroadcastReceiver中指定action是一样的,这样可以精准的投递消息。mode可以指定目标函数执行在哪个线程,默认会执行在UI线程,方便用户更新UI。目标方法执行耗时操作时,可以设置mode为ASYNC,使之执行在子线程中。

3.在其他组件,例如Activity, Fragment,Service中发布事件

EventBus.getDefault().post(new User("android"));

// post a event with tag, the tag is like broadcast‘s action
EventBus.getDefault().post(new User("mr.simple"), "my_tag");

(五)我的实战体验

上面介绍了这么多,下面就说到了我实战中的一些体验,这里我还没有将事件总线应用到真正的项目工程中,写了一个demo测试,代码很简单,这里就不贴出代码了,我写了3个Activity,分别命名为ActivityA,ActivityB,ActivityC,以下简称为A,B,C啦。

1.在A的xml文件中添加一个按钮,增加一个点击事件,在onClick()方法中添加如下代码:

Intent intent = new Intent(A.this,B.class);
intent.putExtra("msg","receive from A");
EventBus.getDefault.postSticky(intent,"toSecond");
startActivity(intent);

2.然后我们在B页面接收A页面传过来的消息,在xml文件中增加一个按钮,添加点击事件,增加一个TextView用来展示消息内容。在B的onCreate()方法添加如下代码:

EventBus.getDefault.registerSticky(this);
textView = (TextView)findViewById(R.id.textview);

在onClick()方法中添加如下代码:

Intent intent = new Intent(B.this,C.class);
startActivity(intent)

创建一个方法通过注解的方式来接收从A传过来的消息,代码如下:

@Subscriber(tag="toSecond")
public void receiveFromA(intent){
    textView.setText(intent.getStringExtra("msg"));
    EventBus.getDefault.removeStickyEvent("toSecond");
}

3.在C的xml文件中添加一个按钮,增加点击事件,代码如下:

Intent intent = new Intent(C.this,B.class);
intent.putExtra("msg","receive from C");
EventBus.getDefault.postSticky(intent,"toSecond");
finish();

下面到了看结果的时候了,相信大家不难看出每个Activity做的事,A发消息并跳转到B,B注册并接收处理消息,点击按钮跳转到C,C点击按钮发送消息并自己finish掉,返回到B,那么现在出现了一个问题,从A发送到消息跳转到B的时候,textview正确的展示了我们传递过来的消息,说明消息被正确的调用处理了,但是当从C发送消息并返回到上一级的时候,textview并没有执行从C返回的数据,后来通过debug调试,发现当我们没有跳转而只是finish返回上一级的时候,由于EventBus.registerSticky()事件被消费掉了,所以从C回到B的事件并不能被监听到,所以没有被处理,大家可以试试,希望这点在以后能够被改善。

  • 希望大家关注我更多的博客,我会不定期更新更多的内容,欢迎大家订阅公众号,我会不定期更新资源,供大家一起学习。

时间: 2024-10-03 23:04:07

AndroidEventBus(事件总线)了解+实战体验的相关文章

AndroidEventBus ( 事件总线 ) 的设计与实现

1. 功能介绍 AndroidEventBus是一个Android平台的事件总线库, 它简化了Activity.Fragment.Service等组件或者对象之间的交互,很大程度上降低了它们之间的耦合,使得我们的代码更加简洁,耦合性更低,提升我们的代码质量. AndroidEventBus吸收了greenrobot的EventBus以及square的otto的优点,并在此基础上做出了相应的改进,使得事件总线框架更适合用户的使用习惯,也使得事件的投递更加的精准.灵活. 与EventBus.otto

Android事件总线

Android事件总线还能怎么玩? 顾名思义,AndroidEventBus ( github链接 ,关于我为什么要写这个库请参考<AndroidEventBus ( 事件总线 ) 的设计与实现>)是一个Android平台的事件总线框架,它简化了Activity.Fragment.Service等组件之间的交互,很大程度上降低了它们之间的耦合,使我们的代码更加简洁,耦合性更低,提升了我们的代码质量.但它能做的却不仅限于这些.经过定制,它能完成很多有意思的功能,那么究竟该怎么做呢?就让我们一起往

Android事件总线 ( AndroidEventBus ) 框架发布

AndroidEventBus AndroidEventBus是一个Android平台的事件总线框架, 它简化了Activity.Fragment.Service等组件之间的交互,很大程度上降低了它们之间的耦合,使得我们的代码更加简洁,耦合性更低,提升我们的代码质量. 在往下看之前,你可以考虑这么一个场景,两个Fragment之间的通信你会怎么实现? 按照Android官方给的建议的解决方法如下: Communicating with the Activity,思路就是Activity实现某个接

AndroidEventBus新特性:添加粘性事件、不需要手动注销事件总线

刚看了下作者发布的新版本AndroidEventBus v1.0.4版本,发现加了很多好东东,最大的两个特性就是添加了粘性sticky事件和无需手动注销事件 AndroidEventBus的github地址为:github 下面是作者给出的粘性sticky事件运用场景,感觉挺给力的,这里直接粘贴复制了 User.java类 : // 实体类实现序列化 public class User { String name ; String phoneNum; // 其他字段省略 public User(

【第一篇】学习 android 事件总线androidEventbus之sticky事件的传递

最近再看eventbus相关代码,首先从使用开始,后期再从源码角度分析eventbus.使用Demo后期公布到github上去. 使用的框架地址:https://github.com/bboyfeiyu/AndroidEventBus Sticky 事件 使用例子: 1,首先每个Activity或者fragement都要进行eventBus的注册和反注册. 发送sticky事件的activity: 1 package com.example.mysimpleeventbus; 2 import

【第三篇】学习 android 事件总线androidEventbus之发布事件,子线程中接收

发送和接收消息的方式类似其他的发送和接收消息的事件总线一样,不同的点或者应该注意的地方: 1,比如在子线程构造方法里面进行实现总线的注册操作: 2,要想子线程中接收消息的功能执行,必须启动线程. 3,添加tag和不添加tag类似其他. 1 package com.example.mysimpleeventbus; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import org.simple.eventbus.Even

android事件总线(eventbus)开源库发布

 AndroidEventBus 如果你不知道事件总线是什么,那么没有关系,下面我们先来看这么一个场景: 你是否在开发的过程中遇到过想在Activity-B中回调Activity-A中的某个函数,但Activity又不能手动创建对象来设置一个Listener什么的? 你是否想在某个Service中想更新Activity或者Fragment中的界面? 等等之类的组件之间的交互问题-- 一经思考,你会发现Android中的Activity, Fragment, Service之间的交互是比较麻烦的,

自己动手写事件总线(EventBus)

本文由云+社区发表 事件总线核心逻辑的实现. EventBus的作用 Android中存在各种通信场景,如Activity之间的跳转,Activity与Fragment以及其他组件之间的交互,以及在某个耗时操作(如请求网络)之后的callback回调等,互相之之间往往需要持有对方的引用,每个场景的写法也有差异,导致耦合性较高且不便维护.以Activity和Fragment的通信为例,官方做法是实现一个接口,然后持有对方的引用,再强行转成接口类型,导致耦合度偏高.再以Activity的返回为例,一

android事件总线(eventbus)设计与实现

1. 功能介绍 AndroidEventBus是一个Android平台的事件总线库, 它简化了Activity.Fragment.Service等组件或者对象之间的交互,很大程度上降低了它们之间的耦合,使得我们的代码更加简洁,耦合性更低,提升我们的代码质量. AndroidEventBus吸收了greenrobot的EventBus以及square的otto的优点,并在此基础上做出了相应的改进,使得事件总线框架更适合用户的使用习惯,也使得事件的投递更加的精准.灵活. 与EventBus.otto