引言
最近在了解RxBus,但被它取代的EventBus也需要熟悉啊,翻了很多的博客,要么讲的很官方,要么代码似是而非,小白根本看不懂啊,这可咋办?偷偷告诉你:“我也是小白!”
于是就有了这篇文章:如何使用EventBus实现activity之间的事件分发-订阅。
效果预览
EventBus.gif介绍
EventBus是一种用于Android的事件发布-订阅总线。它简化了应用程序内各个组件之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。
EventBus三要素
(1)Event:
事件,可以是任意类型的对象。
(2)Subscriber:
事件订阅者,在EventBus3.0之前消息处理的方法只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,他们分别代表四种线程模型。而在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为POSTING)。
(3)Publisher:
事件发布者,可以在任意线程任意位置发送事件,直接调用EventBus的post(Object)方法。可以自己实例化EventBus对象,但一般使用EventBus.getDefault()就好了,根据post函数参数的类型,会自动调用订阅相应类型事件的函数。
EventBus四种线程模型
(1)POSTING(默认):
如果使用事件处理函数指定了线程模型为POSTING,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起应用程序无响应(ANR)。
(2)MAIN:
事件的处理会在UI线程中执行。事件处理时间不能太长,长了会ANR的。
(3)BACKGROUND:
如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
(4)ASYNC:
无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。
用法
第一步:添加依赖(app下build.gradle中)
//EventBus 事件分发-订阅总线
implementation 'org.greenrobot:eventbus:3.1.1'
第二步:布局文件(ActivityA)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".blog.ActivityA"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/btnIntent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="跳转到ActivityB"
android:layout_margin="10dp"
android:textSize="20sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/tvMessage"
app:layout_constraintVertical_chainStyle="packed"
android:textAllCaps="false" />
<TextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:layout_margin="10dp"
app:layout_constraintTop_toBottomOf="@id/btnIntent"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="接受ActivityB返回结果" />
</androidx.constraintlayout.widget.ConstraintLayout>
布局文件(ActivityB中)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".blog.ActivityB"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/btnSend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送事件"
android:textSize="20sp"
android:layout_margin="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:textAllCaps="false" />
</androidx.constraintlayout.widget.ConstraintLayout>
第三步:创建MessageEvent定义消息事件类
package com.example.mydemo.entity;
/**
* @data on 2020/10/15 1:43 PM
* @auther armstrong
* @describe EventBus实战->定义消息事件类
*/
public class MessageEvent {
private String message;
public MessageEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
第四步:在Activity中书写业务逻辑(ActivityA中)
Tips:
下面的点击事件中,我用到了java8中的特性:Lambda表达式,从而省略了重写点击事件的匿名内部类,你可以采用传统的写法new 完OnClickListener重写onClick方法,也可以看我的这篇文章:Lambda表达式告别@override,完成Lambda配置,从而简化你的代码。
//EventBus事件发布-订阅总线探究
public class ActivityA extends AppCompatActivity {
private Button btnIntent;
private TextView tvMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
//EventBus事件发布-订阅总线
initView();
}
private void initView(){
btnIntent = findViewById(R.id.btnIntent);
tvMessage = findViewById(R.id.tvMessage);
tvMessage.setText("千夜零一");
//注册
EventBus.getDefault().register(this);
//点击事件
btnIntent.setOnClickListener((View)->{
startActivity(new Intent(this,ActivityB.class));
});
}
@Subscribe(threadMode = ThreadMode.MAIN) //事件订阅者
public void Event(MessageEvent messageEvent){
tvMessage.setText(messageEvent.getMessage());
}
@Override
protected void onDestroy() {
super.onDestroy();
if(EventBus.getDefault().isRegistered(this)){
EventBus.getDefault().unregister(this);
}
}
}
在Activity中书写业务逻辑(ActivityB中)
//用作EventBus订阅-发布事件总线实战
public class ActivityB extends AppCompatActivity {
private Button btnSend;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
initView();
}
private void initView(){
btnSend = findViewById(R.id.btnSend);
btnSend.setOnClickListener((View)->{
EventBus.getDefault().post(new MessageEvent("这是我的EventBus演示"));
finish();
});
}
}
大功告成!
总结
EventBus在onCreate()方法中注册事件后,需要在onDestory()方法中解注册。
网友评论