EventBus简单介绍
EventBus就是事件总线的意思,个人理解为:我们先把一个个事件(event)发送到总线上,然后EventBus根据已注册的订阅者(subscribers)来匹配相应的事件,进而把事件传递给订阅者处理(可以指定不同的线程处理)。我们在平时开发的时候,当遇到Activity与Activity或者Activity与Fragment之间的通信,往往采用Intent,又或者线程之间使用Handler进行通信,这样代码难免会复杂许多,而使用EventBus能极大简化两个组件之间的通信问题,而且效率极高,而EventBus升级到3.0版本后,开发者能够自定义订阅方法的名字,而没必要规定以“onEventXX”开头的方法了,这样也自由化了很多,而且支持了粘性事件的分发等,因此学会使用EventBus3.0对我们的开发有极大的好处。
一、eventbus组成
EventBus的主要由三个要素组成,分别如下所示:
(1)Event:事件,可以是任意类型的对象。(组件之间通过传递的对象通信)
(2)Subscriber:事件订阅者,他有四种线程处理模型。而在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为POSTING),四种线程模型下面会讲到。
(3)Publisher:事件发布者,可以在任意线程任意位置发送事件,直接调用EventBus的post(Object)方法。可以自己实例化EventBus对象,但一般使用EventBus.getDefault()就好了,根据post函数参数的类型,会自动调用订阅相应类型事件的函数。
接着阐述(2)中所提到的EventBus的四种ThreadMode(线程模型),分别如下所示:
(1)POSTING(默认):如果使用事件处理函数指定了线程模型为POSTING,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。
(2)MAIN: 事件的处理会在UI线程中执行。事件处理时间不能太长,长了会ANR的。
(3)BACKGROUND:如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
(4)ASYNC:无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。
二、使用步骤
EventBus使用起来很简单,分为六个步骤:
1.添加依赖:
compile ‘org.greenrobot:eventbus:3.0.0’
2.自定义一个事件类
public class MessageEvent {
…
}
3.在需要订阅事件的地方注册事件
EventBus.getDefault().register(this);
4.发送事件
EventBus.getDefault().post(messageEvent);
5.处理事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
…
}
6.取消事件订阅
EventBus.getDefault().unregister(this);
三、使用demo
根据上述的使用步骤一步步进行即可,具体demo如下:
首先给出本demo的布局文件。
fragment_msg.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="820"
android:textSize="50sp"
android:gravity="center_horizontal"/>
</LinearLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:background="#6f6669">
<Button
android:layout_gravity="center_horizontal"
android:id="@+id/panhouye"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="伐木机" />
<Button
android:layout_gravity="center_horizontal"
android:id="@+id/bikonghai"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="影魔" />
<Button
android:layout_gravity="center_horizontal"
android:id="@+id/postSticky"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="撼地神牛" />
</LinearLayout>
<FrameLayout
android:id="@+id/framelayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"></FrameLayout>
</LinearLayout>
activity_second.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main2"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30sp"
android:gravity="center_horizontal"
android:id="@+id/tv"
android:text="no data"/>
</RelativeLayout>
(1)在工程app中的gradle中添加依赖:compile ‘org.greenrobot:eventbus:3.0.0’
(2)创建事件类:MessageEvent。代码如下:
/**
* Created by firesmog on 2017/3/14.
*/
public class MessageEvent {
String data;
public MessageEvent() {
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public MessageEvent(String data) {
this.data = data;
}
}
(3)注册事件,这里给出MainActivity
package example.com.myapplication;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button panhouye;
private Button bikonghai;
private Button postSticky;
private MsgFragment msgFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
panhouye= (Button) findViewById(R.id.panhouye);
bikonghai= (Button) findViewById(R.id.bikonghai);
postSticky= (Button) findViewById(R.id.postSticky);
panhouye.setOnClickListener(this);
bikonghai.setOnClickListener(this);
postSticky.setOnClickListener(this);
//添加fragment到右侧的帧布局中
msgFragment = new MsgFragment();
//使用fragment替换掉framelayout getSupportFragmentManager().beginTransaction().add(R.id.framelayout,msgFragment).commit();
}
@Override
protected void onResume() {
super.onResume();
//注册eventbus
EventBus.getDefault().register(this);
}
@Override
protected void onPause() {
super.onPause();
//取消注册
EventBus.getDefault().unregister(this);
}
/**
* 事件发布者(通过按钮点击事件进行事件发布)
* @param v
*/
@Override
public void onClick(View v) {
switch (v.getId()){
//(1)事件发布中所传参数可以作为右侧fragment文本的修改内容
//(2)事件发布中所传参数也可以用作事件订阅者执行方法的区分通知
case R.id.panhouye:
//这里发布事件出去(下同)
EventBus.getDefault().post(new MessageEvent("伐木机"));
break;
case R.id.bikonghai:
EventBus.getDefault().post(new MessageEvent("影魔"));
break;
case R.id.postSticky:
//粘性事件发布(事件发布后,可能目标组件还没有注册事件,然后当目标组件在某个地方注册事
//件时,该注册事件仍然能够接受到注册之前已经发布的事件)
EventBus.getDefault().postSticky(new MessageEvent("撼地神牛"));
startActivity(new Intent(this,SecondActivity.class));
break;
}
}
//在主线程中订阅,即在主线程中处理该事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
// //(1)将事件发布者发布的数据作为文本修改内容
// msgFragment.setText(event.data);
//(2)将事件发布者发布的数据作为方法执行的区分
switch(event.data){
case "伐木机":
msgFragment.setText("转盘");
break;
case "影魔":
msgFragment.setText("影压");
break;
}
}
}
替换掉fragmelayout的fragment代码如下:
/**
* Created by firesmog on 2017/3/14.
*/
public class MsgFragment extends Fragment {
TextView tv;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_msg,container,false);
tv = (TextView) view.findViewById(R.id.tv);
return view;
}
public void setText(String message){
tv.setText(message);
}
}
SecondActivity代码如下:
public class SecondActivity extends AppCompatActivity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
tv = (TextView) findViewById(R.id.tv);
}
@Override
protected void onResume() {
super.onResume();
EventBus.getDefault().register(this);
}
@Override
protected void onPause() {
super.onPause();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void onMessageEvent(MessageEvent event) {
// //(1)将事件发布者发布的数据作为文本修改内容
tv.setText(event.data);
// }
}
}
在demo中,还可以在fragment中注册eventbus并对时间进行订阅处理,实现activity中点击事件传递数据,在fragment中消费。这里感兴趣的可以做一下。
四、结束语
这个demo本身还是比较简单的,代码也都贴了出来,此处就不提供源码了,复制粘贴就可以使用,这里主要是初步了解eventbus的使用,希望大家一起成长学习。