学习原因
为了简化并且高质量地在Activity、Fragment、Thread、Service之间通信,解决高耦合的同时仍能继续高效地通信,有了事件总线的设计。
EventBus三要素
- Event:事件:可以是任何类型的对象
- Subscriber:事件订阅者。在EventBus3.0之前消息处理的方法只能限定于onEvent,onEventMainThread,onEventBackgroundThread和onEventAsync,分别对应四种线程模型。而EventBus3.0之后,事件处理的方法可以随便取名,但是许哟添加一个注解@Subscribe,并且指定线程模型(默认为POSTING)。
- Publisher:事件发布者。可以在任意线程任意位置发送事件,直接调用EventBus的post(Object)方法,可以自己实例化EventBus对象,但一般使用EventBus.getDefault()就可以,根据post函数参数的类型,会自动调用订阅相应类型事件的函数
EventBus四种线程模型
- POSTING:如果使用事件处理函数指定了线程模型为POSTING,那么该事件是在哪一个线程发布出来的,事件函数就会在哪个线程中运行,也就是说发布事件和接收事件在同一个线程中。此模型下要避免耗时操作,会阻碍事件传递,甚至有可能引起ANR
- MAIN:事件的处理会在UI线程中执行,事件处理的时间不能太长,长了会导致ANR
- BACKGROUND:如果事件说是在UI线程中发布出来的,那么该事件处理函数会在新的线程中运行;如果事件本来就是在子线程中发布出来的,那么该事件的处理函数直接在发布事件的线程中执行,在此事件处理函数中禁止进行UI更新操作
- ASYNC:无论事件在哪个线程中发布,该事件处理函数都会在新建的子线程中执行;同样此事件处理函数中禁止执行UI更新操作
EventBus基本用法5个步骤
- 自定义一个事件类
public class MessageEvent{
...
}
- 在需要订阅事件的地方注册事件
EventBus.getDefault().register(this);
- 发送事件
EventBus.getDefault().post(messageEvent);
- 处理事件
@Subscribe(thread = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent){
...
}
- 取消事件订阅
EventBus.getDefault().unregister(this);
简单案例
配置文件
implementation 'org.greenrobot:eventbus:3.0.0'
定义消息事件类MessageEvent
class MessageEvent {
private String Message;
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
public MessageEvent(String message) {
Message = message;
}
}
MainActivity中注册和取消订阅事件
public class MainActivity extends AppCompatActivity {
private TextView tv_message;
private Button bt_message;
private Button bt_subscription;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_message = (TextView)findViewById(R.id.tv_message);
bt_subscription = (Button)findViewById(R.id.bt_subscription);
bt_message = (Button)findViewById(R.id.bt_message);
bt_message.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
bt_subscription.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().register(MainActivity.this);
}
});
}
@Override
protected void onDestroy(){
super.onDestroy();
//取消注册事件
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMoonEvent(MessageEvent messageEvent){
tv_message.setText(messageEvent.getMessage());
}
}
MainActivity对应activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
<Button
android:id="@+id/bt_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="跳转到SecondActivity"/>
<Button
android:id="@+id/bt_subscription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="注册事件"/>
</LinearLayout>
SecondActivity发布事件
public class SecondActivity extends AppCompatActivity {
private Button bt_message;
private TextView tv_message;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
tv_message = (TextView)findViewById(R.id.tv_message);
bt_message = (Button)findViewById(R.id.bt_message);
bt_message.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post(new MessageEvent("欢迎关注简书"));
finish();
}
});
}
}
SecondActivity对应activity_second.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondActivity">
<TextView
android:id="@+id/tv_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SecondActivity"/>
<Button
android:id="@+id/bt_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送事件"/>
</LinearLayout>
proGuard加入混淆规则
-keepattributes *Annotation*
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
此时我们点击MainAc中的“注册事件”按钮来注册事件,然后点击“跳转到SecondActivity”,这时跳转到SecondAc,接下来点击“发送事件”按钮,此时这个SecondAc被finish,同时可以看到MainAc中的TextView被修改,即MainAc成功接收了SecondAc发送的事件。
EventBus黏性事件
上述为普通事件,即要先注册订阅才可以收到发送的消息,黏性事件意为在发送消息之后再订阅也可以收到消息,修改的代码不多,只需要在activity_second.xml中新加入一个Button
<Button
android:id="@+id/bt_subscription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送粘性事件"/>
然后在MainActivity中新加入一个自定义方法用来绑定黏性事件
@Subscribe(threadMode = ThreadMode.POSTING,sticky = true)
public void ononMoonStickyEvent(MessageEvent messageEvent){
tv_message.setText(messageEvent.getMessage());
}
最后在SecondActivity中绑定Button的点击事件即可
private Button bt_subscription;
bt_subscription = (Button)findViewById(R.id.bt_subscription);
bt_subscription.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().postSticky(new MessageEvent("粘性事件"));
finish();
}
});
此时运行我们可以直接跳转到SecondAc而不注册,跳转后点击“发送黏性事件”,SecondAc被finish掉后回到MainAc,此时点击“注册事件”我们可以发现MainAc中的TextView被修改了,完成了黏性事件的发送。
此文仅为个人学习笔记,不以盈利为目的,摘抄自《Android进阶之光——刘望舒》,文字与代码纯手敲完成。
欢迎指正。
网友评论