介绍
GitHub:https://github.com/greenrobot/EventBus
先聊聊EventBus 线程总线是干什么的,使用环境,优点、缺点。
干什么的?
一句话,简单统一数据传递 和 提供主次多个线程
- 数据传递:Android系统有很多类别的数据传递方式,例如Intent 活动之间传递数据、Message与Handler 主次线程之间传递数据、广播的方式、使用基类危险的去传递数据。传递数据的方式太多,且都需要各自的注册方式,使用使用起来比较繁琐。所以EventBus第一个用处是比较统一的去传递数据,特别是碎片、服务、活动,UI线程与子线程 之间的传递,可以有一个比较统一的方式。
- 线程:有了数据就需要逻辑去处理它,相比android系统的数据传递后需要手动创建线程去处理逻辑后,在将得到的数据传到主线程,这一套繁复且反复的传递的过程。EventBus可以很直接的在对应线程方法里去直接互相传递处理。
使用环境
多个地方需要传递数据和相应线程逻辑处理环境,比如碎片+上下活动+服务+广播+线程的情况下,你可以想象一下为了这些数据处理需要敲不少的代码。EventBus 线程可以统一的管理,只需要在对应类里注册它。
优点
- 简单统一数据传递
- 清晰明了的主次线程
- 使用class传递数据(是的,最好用的地方用一个class来传递数据,这下传一个class,就可以携带各种各样的数据了,摆脱了用Bundle传递list和数组简直太爽了)
缺点
让我研究一下它的局限性在写
使用方式:
1.添加依赖
implementation 'org.greenrobot:eventbus:3.1.1'
2.添加注册
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_bus_demo);
EventBus.getDefault().register(this);//注册
}
3.注销
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
4.传递数据准备,创建数据类
public class MsgData {
private String msg;
public MsgData(String msg){
this.msg = msg;
}
public String getmsg() {
return msg;
}
}
5.注册发送事件与发送数据
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
EventBus.getDefault().post(new MsgData("send"));//注册,发送的是上面创建的数据class
}
});
6.处理接收事件与线程
上面5个步骤都很简单,接收与线程稍微有一些需要解释:
4种线程模式:
- POSTING:Event处理函数在发布Event的线程中执行。(ANR)
- MAIN:Event处理函数在UI线程中执行。(ANR)
- BACKGROUND:如果发布Event的线程是UI线程,Event处理函数就新建子线程中执行;如果发布Event的线程是子线程,那么就在当前子线程执行。(不允许修改UI)
- ASYNC:新建子线程执行Event处理函数,新建的线程与UI线程八竿子打不着。(所以别在这里处理UI)
创建上面四种线程方法:
这些线程不是需要抽象重写或者接口的重写方法,需要自己创建一个方法,使用注释@Subscribe添加自己需要的线程模式,
下面就是创建了UI主线程方法的例子:
@Subscribe(threadMode = ThreadMode.MAIN,sticky = false)
public void onUiMain(MsgData msgData){
if (msgData.getmsg().equals("send")) { //得到发送过来的数据
mContent.setText("接收到了数据");
}
}
7.粘性事件
黏性事件,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。粘性事件与普通事件创建一样,只是有细微不同。
发送粘性事件:
MsgData msgData = new MsgData("我是粘性数据");
EventBus.getDefault().postSticky(msgData);//注意,这里使用的是postSticky发送粘性事件
接收粘性事件:
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true) //重点,这里的sticky 设置为了true
public void onUiMain(MsgData msgData){
if (msgData.getmsg().equals("我是粘性数据")) {
mContent.setText("接收粘性数据");
}
}
粘性事件会一直保存在内存中,等待后续的接收粘性事件方法的创建与接收,因为会一直停留在内存里,所以我们需要去清理粘性事件,粘性事件接收到了确定无用后就清理是个好习惯。
- 移除指定的粘性事件:removeStickyEvent(Object event);
- 移除指定类型的粘性事件:removeStickyEvent(Class<T> eventType);
- 移除所有的粘性事件:removeAllStickyEvents();
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void onUiMain(MsgData msgData){
if (msgData.getmsg().equals("粘性数据")) {
mContent.setText("接收到了数据");
}
if(EventBus.getDefault().removeStickyEvent(msgData)){
Toast.makeText(this,"清理粘性事件成功",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this,"清理粘性事件失败",Toast.LENGTH_SHORT).show();
}
}