1、EventBus 简介

EventBus是一种用于Android的事件发布-订阅总线,由GreenRobot开发,Gihub地址是:EventBus。它简化了应用程序内各个组件之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。

1.1 三个角色

  1. Event:事件,它可以是任意类型,EventBus会根据事件类型进行全局的通知。
  2. Subscriber:事件订阅者,在EventBus 3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEventonEventMainThreadonEventBackgroundThreadonEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe,并且指定线程模型,默认是POSTING
  3. Publisher:事件的发布者,可以在任意线程里发布事件。一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。

EventBus的四种线程模型(ThreadMode)

  • POSTING(默认):如果使用事件处理函数指定了线程模型为POSTING,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起应用程序无响应(ANR)。
  • MAIN:事件的处理会在UI线程中执行。事件处理时间不能太长,长了会ANR的。
  • BACKGROUND:如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
  • ASYNC:无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。

使用步骤

   添加依赖

implementation 'org.greenrobot:eventbus:3.1.1'
  • 注册:EventBus.getDefault().register(this);
  • 解注册(为防止内存泄漏):EventBus.getDefault().unregister(this);
  • 构造发送消息类

public class MessageWrap {public final String message;public static MessageWrap getInstance(String message) {return new MessageWrap(message);}private MessageWrap(String message) {this.message = message;}
}
  • 发布消息:EventBus.getDefault().post(new MessageEvent(“name”,”password”));
  • 接收消息:可以有四种线程模型选择

@Subscribe(threadMode = ThreadMode.MAIN)
public void messageEventBus(MessageEvent event){tv_result.setText("name:"+event.name+" passwrod:"+event.password);
}

发布事件

然后,我们定义一个Activity:

@Route(path = BaseConstants.LIBRARY_EVENT_BUS_ACTIVITY1)
public class EventBusActivity1 extends CommonActivity<ActivityEventBus1Binding> {@Overrideprotected void doCreateView(Bundle savedInstanceState) {// 为按钮添加添加单击事件getBinding().btnReg.setOnClickListener(v -> EventBus.getDefault().register(this));getBinding().btnNav2.setOnClickListener( v ->ARouter.getInstance().build(BaseConstants.LIBRARY_EVENT_BUS_ACTIVITY2).navigation());}@Overrideprotected void onDestroy() {super.onDestroy();EventBus.getDefault().unregister(this);}@Subscribe(threadMode = ThreadMode.MAIN)public void onGetMessage(MessageWrap message) {getBinding().tvMessage.setText(message.message);}
}

这里我们当按下按钮的时候向EventBus注册监听,然后按下另一个按钮的时候跳转到拎一个Activity,并在另一个Activity发布我们输入的事件。在上面的Activity中,我们会添加一个监听的方法,即onGetMessage,这里我们需要为其加入注解Subscribe并指定线程模型为主线程MAIN。最后,就是在Activity的onDestroy方法中取消注册该Activity。

下面是另一个Activity的定义,在这个Activity中,我们当按下按钮的时候从EditText中取出内容并进行发布,然后我们退出到之前的Activity,以测试是否正确监听到发布的内容。

@Route(path = BaseConstants.LIBRARY_EVENT_BUS_ACTIVITY2)
public class EventBusActivity2 extends CommonActivity<ActivityEventBus2Binding> {@Overrideprotected void doCreateView(Bundle savedInstanceState) {getBinding().btnPublish.setOnClickListener(v -> publishContent());}private void publishContent() {String msg = getBinding().etMessage.getText().toString();EventBus.getDefault().post(MessageWrap.getInstance(msg));ToastUtils.makeToast("Published : " + msg);}
}

根据测试的结果,我们的确成功地接收到了发送的信息。

黏性事件

所谓的黏性事件,就是指发送了该事件之后再订阅者依然能够接收到的事件。使用黏性事件的时候有两个地方需要做些修改。一个是订阅事件的地方,这里我们在先打开的Activity中注册监听黏性事件:

@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onGetStickyEvent(MessageWrap message) {String txt = "Sticky event: " + message.message;getBinding().tvStickyMessage.setText(txt);
}

另一个是发布事件的地方,这里我们在新的开的Activity中发布黏性事件。即调用EventBus的postSticky方法来发布事件:

private void publishStickyontent() {String msg = getBinding().etMessage.getText().toString();EventBus.getDefault().postSticky(MessageWrap.getInstance(msg));ToastUtils.makeToast("Published : " + msg);
}

按照上面的模式,我们先在第一个Activity中打开第二个Activity,然后在第二个Activity中发布黏性事件,并回到第一个Activity注册EventBus。根据测试结果,当按下注册按钮的时候,会立即触发上面的订阅方法从而获取到了黏性事件。

优先级

Subscribe注解中总共有3个参数,上面我们用到了其中的两个,这里我们使用以下第三个参数,即priority。它用来指定订阅方法的优先级,是一个整数类型的值,默认是0,值越大表示优先级越大。在某个事件被发布出来的时候,优先级较高的订阅方法会首先接受到事件。

为了对优先级进行测试,这里我们需要对上面的代码进行一些修改。这里,我们使用一个布尔类型的变量来判断是否应该取消事件的分发。我们在一个较高优先级的方法中通过该布尔值进行判断,如果未true就停止该事件的继续分发,从而通过低优先级的订阅方法无法获取到事件来证明优先级较高的订阅方法率先获取到了事件。

这里有几个地方需要注意

  1. 只有当两个订阅方法使用相同的ThreadMode参数的时候,它们的优先级才会与priority指定的值一致;
  2. 只有当某个订阅方法的ThreadMode参数为POSTING的时候,它才能停止该事件的继续分发。

所以,根据以上的内容,我们需要对代码做如下的调整:

// 用来判断是否需要停止事件的继续分发
private boolean stopDelivery = false;@Override
protected void doCreateView(Bundle savedInstanceState) {// ...getBinding().btnStop.setOnClickListener(v -> stopDelivery = true);
}@Subscribe(threadMode = ThreadMode.POSTING, priority = 0)
public void onGetMessage(MessageWrap message) {getBinding().tvMessage.setText(message.message);
}// 订阅方法,需要与上面的方法的threadMode一致,并且优先级略高
@Subscribe(threadMode = ThreadMode.POSTING, sticky = true, priority = 1)
public void onGetStickyEvent(MessageWrap message) {String txt = "Sticky event: " + message.message;getBinding().tvStickyMessage.setText(txt);if (stopDelivery) {// 终止事件的继续分发EventBus.getDefault().cancelEventDelivery(message);}
}

即我们在之前的代码之上增加了一个按钮,用来将stopDelivery的值置为true。该字段随后将会被用来判断是否要终止事件的继续分发,因为我们需要在代码中停止事件的继续分发,所以,我们需要将上面的两个订阅方法的threadMode的值都置为ThreadMode.POSTING

按照,上面的测试方式,首先我们在当前的Activity注册监听,然后跳转到另一个Activity,发布事件并返回。第一次的时候,这里的两个订阅方法都会被触发。然后,我们按下停止分发的按钮,并再次执行上面的逻辑,此时只有优先级较高的方法获取到了事件并将该事件终止。

Android 泽宇_EventBus的使用相关推荐

  1. Android 泽宇Glide和Picasso框架之间的区别与应用

    Glide和Picasso是目前Android开发中很流行的图片加载库,Glide库和Picasso库也有极大的相似性,这篇文章就通过对比的方式描述一下这个两个功能强大的优秀库的使用. 一.简介: 1 ...

  2. Android 泽宇节操视频

    今天我要介绍的是节操视频,此框架的小编个人感觉还是很好用的,轻轻松松的几行代码就搞定了 1.所用依赖:implementation 'fm.jiecao:jiecaovideoplayer:5.5' ...

  3. Android 泽宇App广告栏

    在介绍具体的使用说明之前,我们先看一下简单的实现效果: 使用说明 显示一个默认广告弹窗,支持单广告活动.多广告活动,当弹窗显示多广告是默认显示底部小圆圈,当显示单活动时默认不显示底部小圆圈: 默认支持 ...

  4. Android 泽宇二级列表

    在开发 Android APP 的时候,难免会需要实现二级列表的情况,而在自己的项目中使用的列表是ExpandableListView 如若转发标明转载处:https://mp.csdn.net/po ...

  5. Android 泽宇GC垃圾回收机制算法

    GC是什么? GC的英文全称是:Gabage Collection,翻译成中文就是垃圾回收的意思.在一个对象不再被程序引用时,它所占用的堆空间就可以回收,以便于分配给新的对象使用. 那我们在了解回收机 ...

  6. Android 泽宇三种底部导航栏

    compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.0.8@aar'//底部导航 <com.flyco.tablayout.CommonTabLa ...

  7. Android 泽宇多布局

    现在的速度跟新的速度越来越快,手机的开发,变更也日夜加快普通的已经不能满足我们的需求了,我们看下面一张图 多布局 这张图就是一个简简单单的多布局,然而我们要是用普通的的视频去实现要写的代码量很多看着也 ...

  8. Android 泽宇Retrofit+Rxjava

    今天就写一个简单的Retrofit+Rxjava的联合运用的代码 这是一个请求的接口返回给观察者 Observable是被观察者,Observe是观察者 @FormUrlEncoded @POST(& ...

  9. Android 泽宇管理Fragment的方法

    public Fragment addFragment(int id, Class<Fragment> fragmentClass, Map<String,String> ma ...

最新文章

  1. python if语句多个条件-python if条件判断语句
  2. 网狐荣耀版通过水浒传基础二开埃及拉霸和水果森林步骤
  3. leetcode 44 字符匹配
  4. 视觉错觉模型_有才!将立体模型涂改伪装成平面二次元,视觉错觉玩法在日本风靡...
  5. Asp: 解决脚本输出网页出现乱码情况
  6. Objective-C 2.0 with Cocoa Foundation--- 8,类方法以及私有方法
  7. 1024告诉身边的程序员,今天他过节日
  8. 以太网接入设备行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  9. python输入数字输出中文_go格式“占位符”, 输入输出,类似python的input
  10. vue使用laydate.js插件报错laydate.css: Invalid
  11. Android APP 稳定性测试工具—Fastboot使用教程
  12. iOS开发捷径学习(一)
  13. php计算macd,MT4里的MACD和平常所用的MACD计算公式是什么?
  14. oracle根据身份证号码计算年龄
  15. Vue提示 , Vue指令提示, Vue代码提示 Pycharm中引用vue不显示提示
  16. TweenMax 参数说明
  17. (1)语言是什么——NLP的语言基础
  18. Python 利用多线程进行爬虫(一)
  19. 3d Max安装失败(Microsoft Visual C++ 2010 Redistributable)
  20. Web前端:中国环宇科技有限公司网页设计

热门文章

  1. 住房信息平台添加发布房源功能
  2. 【IT】福昕pdf保持工具选择
  3. 有什么调整视频播放速度的方法吗?
  4. Vue3电商项目实战-结算支付 3【05-结算-收货地址-添加、06-结算-收货地址-修改、07-结算-提交订单】
  5. 公司停电,程序员去网吧写代码;iPhone 14将于北京时间9月8日发布;GitLab修复一个关键远程代码执行漏洞|极客头条
  6. 【前端】常见英文缩写汇总、解析(持续更新...)
  7. DevOps是什么?DevOps能够给我们带来什么?
  8. 怎么做加减计算机程序vb,如何用VB设计一个简单计算器能进行加减乘除运算?...
  9. 手机微信表白弹窗,用微信就能撩到小姐姐小哥哥!!!
  10. GM Right Mouse Pro for Mac,鼠标右键增强工具