EventBus基本用法
小知识
耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。
解耦就是用数学方法将两种运动分离开来处理问题,常用解耦方法就是忽略或简化对所研究问题影响较小的一种运动,只分析主要的运动。
不准确的讲 解耦就是将问题分开处理 。就像老炮儿里的桥段一样,我无证摆摊车子应该被你收走。你打我一巴掌,这个事是另外一件事,我得打回来。言归正传。。。。
Github地址
[EventBus]https://github.com/greenrobot/EventBus
定义
EventBus是一种用于Android的事件发布-订阅总线,由GreenRobot开发。
这是官方的话,我就抄一句。说白了就是一个舍友做完了题,把结果发给其他众多不会做的舍友。优生就是被订阅者,其他舍友就是订阅者,扔小抄就是发布事件,小抄就是事件。
组件间传统的通信方式:
- Handler 2. BroadcastReceiver 3. Interface回调
优点:
1.使用简单
2.切换线程方便
3.使用class可以传递各种数据
4.可以在四大组件,fragment间传递。
缺点
1.建了好多自定义类 不易于管理
2.EventBus也并不是绝对的解耦。
角色
-Event 事件,它可以是任意类型,EventBus会根据事件类型进行全局的通知。
说白了就是优生的考试题答案。根据事件类型 的意思就是英语答案扔给和你提前说好的英语不好的 那群 舍友,数学答案扔给 那个 需求数学答案的舍友,按需供给嘛。这里可以是一群 可以是一个 不强求。
Subscriber 事件订阅者,要带指定的线程模型,默认是 POSTING。
就那些个不好好复习的。
Publisher 事件的发布者。
会做的那个,做完了会扔出来答案的人。
四种线程模型
在下面之前我打个比方 比如:
主线程就是 A教室 监考比较严的考场 在这里只能考试
其他线程就是 B教室 C教室。。。可以干其他的
假设你就是那个不好好复习 摸鱼的。
MAIN 表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
意思是你在A教室考试 在这里收到答案后 只能考试 不能做其他特别费时间的事情 比如 在桌子上刻字,唱歌。
POSTING (默认) 表示事件处理函数的线程跟发布事件的线程在同一个线程。
意思就是你和优生默认在一个教室考试 他在A教室考你就在A 他在其他就在其他 当然在A的时候不可以干其他的 除了A你可以可以刻字或者扔粉笔头儿。
BACKGROUND 表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
意思是优生如果在A教室考 那你就在其他教室 如果优生在B或者其他 那你就跟他一个教室 在A教室的时候收到答案只能考试 其他可以随便。。。
ASYNC 表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
意思就是 不管优生在哪个教室 收答案的都被拉出来新分到一个教室 而且这个教室不是主考场 你随便干什么都行。。
使用
普通用法
1.在app的build.gradle引入
dependencies { //EventBus
implementation 'org.greenrobot:eventbus:3.2.0'
}
2.写一个自定义类 可以随便
public class MessageBean {
String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
3.写一个接收数据的类EventBusActivityRx
package laern;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.blankj.utilcode.util.ToastUtils;
import com.example.syn.BaseActivity;
import com.example.syn.R;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import Bean.MessageBean;
public class EventBusActivityRx extends BaseActivity {
private TextView result;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_eventbus);
EventBus.getDefault().register(this);
initView();
}
private void initView() {
result = (TextView) findViewById(R.id.result);
result.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(EventBusActivityRx.this,EventBusActivityTx.class));
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onGetMessage(MessageBean message) {
//这里接收message
if (result != null)
result.setText(message.getMessage());
}
}
这里只布局了一个textview 用来显示和接受数据。在onCreate中注册了EventBus ,在onDestroy中取消了注册。然后点击跳转到了发射数据的类。
4.写一个数据发射类EventBusActivityTx
package laern;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.example.syn.BaseActivity;
import com.example.syn.R;
import org.greenrobot.eventbus.EventBus;
import Bean.MessageBean;
/**
*
*/
public class EventBusActivityTx extends BaseActivity implements View.OnClickListener {
private Button mJumpTo;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_eventbustx);
initView();
}
private void initView() {
mJumpTo = (Button) findViewById(R.id.jumpTo);
mJumpTo.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
default:
break;
case R.id.jumpTo:
MessageBean bean = new MessageBean();
bean.setMessage("发射。。");
EventBus.getDefault().post(bean);
finish();
break;
}
}
}
这里只布局了一个按钮,发送了一个数据 “发射“ ,然后回退到接受数据的类EventBusActivityRx中,在接受数据的类中看是否显示数据。
这里我们成功拿到了数据。我们这里是EventBusActivityRx 跳转到了EventBusActivityTx ,因为在EventBusActivityRx中已经注册了EventBus,所以会退回来的时候有数据。但在有些时候,我们是直接EventBusActivityTx 跳转到EventBusActivityRx中而不是回退,这时EventBusActivityRx中的EventBus还没被注册,此时接受不到数据。想要接收到数据就需要粘性事件。
粘性事件
我们对发射类点击事件做下修改,改为跳转到数据接收类
case R.id.jumpTo:
MessageBean bean = new MessageBean();
bean.setMessage("发射。。");
EventBus.getDefault().postSticky(bean);
startActivity(new Intent(EventBusActivityTx.this,EventBusActivityRx.class));
break;
接受类中接收方法做下修改,将粘性事件开关打开。
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void onGetMessage(MessageBean message) {
//这里接收message
if (result != null)
result.setText(message.getMessage());
}
我们在发射类点发射,此时接收类中EventBus还没被注册。如果不加sticky = true ,我们接收不到,加了可以接收到。这个可以自己试试。
priority优先级
它用来指定订阅方法的优先级,是一个整数类型的值,默认是0,值越大表示优先级越大。在某个事件被发布出来的时候,优先级较高的订阅方法会首先接受到事件。
其实就是几个接受方法中,在同一个线程中会根据priority的大小,接收数据,优先级高的当线程为POSTING时 接收到后可以通过
EventBus.getDefault().cancelEventDelivery(message);
关闭事件的传递。这里我们直接复制
package laern;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.example.syn.BaseActivity;
import com.example.syn.R;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import Bean.MessageBean;
/**
*
*/
public class EventBusActivityRx extends BaseActivity {
private TextView result;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_eventbus);
EventBus.getDefault().register(this);
initView();
}
private void initView() {
result = (TextView) findViewById(R.id.result);
result.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(EventBusActivityRx.this,EventBusActivityTx.class));
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.POSTING,sticky = true,priority = 1)
public void onGetMessageSticky(MessageBean message) {
//这里接收message
Log.d("priority", "粘性事件接收到参数 priority = 1");
}
@Subscribe(threadMode = ThreadMode.POSTING,priority = 1)
public void onGetMessage(MessageBean message) {
//这里接收message
Log.d("priority", "接收到参数 priority = 1");
}
}
我们对数据接受类做了下修改,接受方法一个为粘性 一个非粘性,优先级一样。我们从数据接受类跳转到发射类,然后回退之后得到打印。

发现都可以接收到,我们修改优先级
@Subscribe(threadMode = ThreadMode.POSTING,sticky = true,priority = 1)
public void onGetMessageSticky(MessageBean message) {
//这里接收message
Log.d("priority", "粘性事件接收到参数 priority = 1");
}
@Subscribe(threadMode = ThreadMode.POSTING,priority = 2)
public void onGetMessage(MessageBean message) {
//这里接收message
Log.d("priority", "接收到参数 priority = 2");
}
得到

发现优先级高的先收到,然后我们添加取消消息继续传送
@Subscribe(threadMode = ThreadMode.POSTING,sticky = true,priority = 1)
public void onGetMessageSticky(MessageBean message) {
//这里接收message
Log.d("priority", "粘性事件接收到参数 priority = 1");
}
@Subscribe(threadMode = ThreadMode.POSTING,priority = 2)
public void onGetMessage(MessageBean message) {
//这里接收message
Log.d("priority", "接收到参数 priority = 2");
EventBus.getDefault().cancelEventDelivery(message);
}
得到

发现确实在级别高的地方收到之后 消息被取消了 priority = 1的地方就没打印。也证明了优先级问题。
其他:
介绍一个和EventBus类似功能的控件
[BusUtils]https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/src/main/java/com/blankj/utilcode/util/BusUtils.java
据说对比效率比EventBus高 大家可以试试