方法 | 特点 |
---|---|
EventBus | 开销小,代码更优雅,将发送者和接收者解耦 |
Otto | 降低程序之间的耦合性 |
EventBus是一个发布-订阅的事件总线。Event Bus模式也被称之为Message Bus或者发布者-订阅者模式,它简化了应用程序内各组件间、组件与后台线程间的通信,可以让两个组件相互通信,但是它们之间并不相互知晓(有些类似于广播机制)。其优点是开销小,代码更优雅,以及将发送者和接收者解耦。其主要功能是用来替代传统的Intent、Handler、Broadcast在Fragment、Activity、Service以及线程之间传递消息。
目前有多个库都开发了这样的功能。比如说:Google guava 开源库,位于com.google.common.eventbus包下面。但是guava项目比较大,比较常用在j2ee项目内。我们在android开发中实际用的是greenrobot 开发的EventBus。它有以下的优点:1、方法库较小,便于集成。guava jar包2.2M,greenrobot 54k;2、使用简单;
EventBus是彻底解耦的观察者模式。我们常常用在对象一对多的情况,使一个对象发生改变的时候,所有依赖的对象能够得到通知并更新。比如我们在实际的开发中,当用户登录了,我们多个页面需要根据登录后的信息更改页面UI。这时,登录界面就是发布者,而其他的页面就是订阅者。它们都在订阅用户信息变化的消息。再比如我们的Fragment间的通信。
优点:1、开发简便;2、代码耦合度降低;3、插件大小合适,仅54k;
缺点:由于是松耦合设计,导致代码维护差,发送出来的事件不知道有多少个接收者。
(1)发送者(Publisher)首先把它的事件(Event)传递到事件总线(EventBus)里面进行管理,等待分发。
(2)事件总线(EventBus)按照相应的逻辑,遍历所有已经注册事件(Event)的订阅者(Subscribe),找到onEvent()方法,把事件(Event)发布给订阅者(Subscriber)。
(3)订阅者(Subscriber)接收到数据(通过对应方法进行接收),进行相应的处理。
元素名称 | 说明 |
---|---|
Event | 事件 |
Subscriber | 事件订阅者,接收特定的Event事件 |
Publisher | 事件发布者,用于通知Subscriber有事件发生 |
Event:事件。它可以是任意类型。
Subscriber:事件订阅者。在EventBus3.0之前我们必须定义onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync四种方法,它们代表四种线程模型。而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
Publisher:事件的发布者。可以在任意线程任意位置发布事件,直接调用EventBus的post(Object)方法。一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。
EventBus3.0有四种线程模型,分别是:
POSTING (默认):表示发布事件和接收事件在同一个线程。
MAIN:表示事件处理会在主线程(UI)线程执行,因此在这里不能进行耗时操作。
BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
EventBus的基本用法包括订阅、注册、发布、取消注册。
1、注册:
EventBus.getDefault().register(this);
EventBus.getDefault().register(new MyClass());
//注册:三个参数分别是,消息订阅者(接收者),接收方法名,事件类
EventBus.getDefault().register(this,“setTextA”,SetTextAEvent.class);
2、取消注册:
EventBus.getDefault().unregister(this);
EventBus.getDefault().unregister(new MyClass());
3、订阅处理数据:
public void onEventMainThread{}
public void onEvent(AnyEventType event) {}
onEventPostThread、onEventBackgroundThread、onEventAsync
4、发布:
EventBus.getDefault().postSticky(new SecondActivityEvent(“Message From SecondActivity”));
EventBus.getDefault().post(new ChangeImgEvent(1));
@Subscribe(threadMode = ThreadMode.MAIN)
public void getEventBus(MyEvent event){
}
threadMode 就是旧版本接收信息运行的方法。
在Android Studio中不需要下载jar包,直接添加依赖即可:
compile 'org.greenrobot:eventbus:3.0.0'
项目简介:使用EventBus进行事件的注册、订阅和发布。
项目地址:https://github.com/ambition-hb/EventBusDemo
项目图示:
首先点击MainActivity中的“注册事件”按钮来注册事件,然后点击“调转到SecondActivity”按钮,这时跳转到SecondActivity,接下来点击“发送事件”按钮,这个时候SecondActivity被finish掉,因此界面显示的是MainActivity以及TextView“您已收到SecondActivity发送的事件!”,至此,MainActivity成功地收到了SecondActivity发送的事件。
部分代码如下:
//1、MessageEvent.java
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;
}
}
//2、MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button bt_message;//跳转到SecondActivity
private Button bt_subscription;//注册事件
private TextView tv_message;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_subscription = (Button)findViewById(R.id.bt_subscription);
bt_message = (Button)findViewById(R.id.bt_message);
tv_message = (TextView)findViewById(R.id.tv_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);
}
//事件订阅者处理事件,用TexiView来展示接收到的事件消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMoonEvent(MessageEvent messageEvent){
tv_message.setText(messageEvent.getMessage());
}
}
//3、SecondActivity.java
public class SecondActivity extends AppCompatActivity {
private Button bt_message;
private TextView tv_messgae;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
tv_messgae = (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("您已收到SecondActivity发送的事件!"));
finish();//发送事件并将SecondActivity finish掉
}
});
}
}
除了以上的普通事件外,EventBus还支持发送粘性事件,就是在发送事件之后再订阅该事件也能收到该事件。(类似于粘性广播)
项目简介:使用EventBus的黏性事件进行注册、订阅和发布。
项目地址:https://github.com/ambition-hb/EventBusStickyEventDemo
项目图示:
首先,我们在MainActivity中不点击“注册事件”按钮,而是直接跳转到SecondActivity中点击“黏性事件”按钮。这时界面回到MainActivity,我们看到TextView仍旧显示着MainActivity的字段,因为我们还没有订阅事件。接下来点击“注册事件”按钮,TextView内容发生改变,显示“黏性事件”,说明黏性事件被成功接收。
部分代码如下:
//1、MessageEvent
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;
}
}
//2、MainActivity
public class MainActivity extends AppCompatActivity {
private Button bt_message;//跳转到SecondActivity
private Button bt_subscription;//注册事件
private TextView tv_message;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_subscription = (Button)findViewById(R.id.bt_subscription);
bt_message = (Button)findViewById(R.id.bt_message);
tv_message = (TextView)findViewById(R.id.tv_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);
}
//事件订阅者处理黏性事件,用TexiView来展示接收到的事件消息
@Subscribe(threadMode = ThreadMode.POSTING, sticky = true)
public void onMoonStickyEvent(MessageEvent messageEvent){
tv_message.setText(messageEvent.getMessage());
}
}
//3、SecondActivity
ublic class SecondActivity extends AppCompatActivity {
private Button bt_message;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
bt_message = (Button)findViewById(R.id.bt_message);
bt_message.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().postSticky(new MessageEvent("黏性事件"));
finish();//发送事件并将SecondActivity finish掉
}
});
}
}
otto 是 Square公司发布的一个发布-订阅模式框架,它基于Google Guava 项目中的event bus模块开发,针对Android平台做了优化和加强。(Square已经停止了对otto的更新并推荐使用RxJava和RxAndroid来替代它)otto基于Guava项目的Android支持库,如果你在Android程序开发的过程中想要不同的组件之间进行有效的通信可以使用这个库。通过otto库可以降低程序之间的耦合性。
Otto中真正用到的就只有一个类两个注解三个方法:
1、Bus – 管理注册、注销和发布事件
2、@Produce – 标记该方法是生产者,产生的事件内容为该方法的返回值
3、@Subscribe – 标记该方法是订阅者,表示订阅了一个事件,方法需要修饰符 为public,而区分不同的订阅者是通过方法的参数来区分的,且订阅了某事件的所有订阅者都可以收到该事件
4、register(Object obj) – 注册,订阅事件前都需要注册
5、unregister(Object obj) – 注销,放弃之前所有事件的订阅
6、post(Object event) – 发布一个事件,这个事件会被所有标记了@Subscribe注解的方法获得
在Android Studio中不需要下载jar包,直接添加依赖即可:
compile 'org.greenrobot:eventbus:3.0.0'
项目简介:使用Otto进行事件的注册、订阅和发布。
项目地址:https://github.com/ambition-hb/OttoDemo
项目图示:
首先,我们点击MainActivity的“跳转到SecondActivity”按钮直接跳转到SecondActivity,再点击“发生事件”按钮,SecondActivity被finish掉,回到MainActivity,MainActivity中textView的文字变为"MainActivity更新啦!"。
//1、BusData
public class BusData {//定义消息类
public String message;
public BusData(String message){
this.message = message;
}
public String getMessage(){
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
//2、OttoBus
public class OttoBus extends Bus {
//otto的Bus类相当于EventBus中的EventBus类,它封装了otto的主要功能。
//但它不是一个单例,其每次都要用new创建出来,因此我们使用单例模式将他封装起来。
private volatile static OttoBus bus;
private OttoBus(){
}
public static OttoBus getInstance(){
if (bus == null){
synchronized (OttoBus.class){
if (bus == null){
bus = new OttoBus();
}
}
}
return bus;
}
}
//3、MainActivity
public class MainActivity extends AppCompatActivity {
private TextView tv_message;
private Button bt_jump;
//otto同样需要注册和取消注册、订阅事件
private Bus bus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_message = (TextView)findViewById(R.id.tv_message);
bt_jump = (Button)findViewById(R.id.bt_jump);
bt_jump.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, SecondActivity.class));
}
});
//通过OttoBus得到Bus对象
bus = OttoBus.getInstance();
//调用Bus的register方法来注册和取消注册
bus.register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//调用Bus的unregister方法来注册和取消注册
bus.unregister(this);
}
//订阅事件
@Subscribe
public void setContent(BusData data){
//使用textView来显示接收到的消息
tv_message.setText(data.getMessage());
}
}
//4、SecondActivity
public class SecondActivity extends AppCompatActivity {
private Button bt_send;
private OttoBus bus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
bt_send = (Button)findViewById(R.id.bt_send);
bt_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
OttoBus.getInstance().post(new BusData("MainActivity更新啦!"));
finish();
}
});
}
}