开源项目链接

背景介绍

如果你学习过设计模式,那么当想通知其他组件某些事情发生时你一定会使用观察者模式。好了,既然能想到这个设计模式,那么就来看一个屌爆天的Android开源框架EventBus。主要功能是替代Intent、Handler、BroadCast在Fragment、Activity、Service、线程之间传递消息。他的最牛逼优点是开销小,代码简洁,解耦代码。

基础介绍

上面说了,EventBus是一个观察者模式的实现,既然这样,那他就有如下三个要素:

Event:事件

Subscriber:事件订阅者,接收特定的事件。

Publisher:事件发布者,用于通知Subscriber有事件发生。

其中,Event可以使任意类型对象。Subscriber都是以约定的onEvent开头的函数,具体是onEvent,onEventMainThread,onEventBackgroundThread,onEventAsync这四个。Publisher可以通过post(Object)在任意线程任意位置发送事件。

官方这个图就很直观的说明了这种观察者模式的架构:

fc2aaee948cabca487f058eb95557db9.png

依据开源库组件的说明文档来操作:

在工程gradle中添加:compile ‘de.greenrobot:eventbus:2.4.0’。

按照文档HOWTO.md进行操作。

Subscriber以onEvent开头的4个函数区别:

onEvent:事件的处理在和事件的发送在相同的线程,所以事件处理时间不应太长,不然影响事件的发送线程。

onEventMainThread: 事件的处理会在UI线程中执行。事件处理时间不能太长,长了会出现臭名远之的ANR。

onEventBackgroundThread:事件的处理会在一个后台线程中执行。虽然名字是BackgroundThread,事件处理是在后台线程,但事件处理时间还是不应该太长,因为如果发送事件的线程是后台线程,会直接在当前后台线程执行事件;如果当前线程是UI线程,事件会被加到一个队列中,由一个线程依次处理这些事件,如果某个事件处理时间太长,会阻塞后面的事件的派发或处理。

onEventAsync:事件处理会在单独的线程中执行,主要用于在后台线程中执行耗时操作,每个事件会开启一个线程,但最好限制线程的数目。

下面还是先上代码再总结分析。

实战一把屌爆天的功能

如下示例演示了EventBus的线程间通信与线程内通信及自定义消息结构的通信。

如下是主界面显示效果:

6bae09614b197e6d3afab5008c7f5f67.png

接着看代码:

首先自定义一个消息数据类型,如下:

public class MsgBean {

private String msg;

public MsgBean(String msg) {

this.msg = msg;

}

public String getMsg() {

return msg;

}

public void setMsg(String msg) {

this.msg = msg;

}

}

接着编写主界面及逻辑代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private TextView mShowInfo1, mShowInfo2, mShowInfo21, mShowInfo22;

private Button mBtn1, mBtn2, mBtn21, mBtn22;

private int mCount = 0;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initData();

}

private void initData() {

mShowInfo1 = (TextView) findViewById(R.id.first_show);

mBtn1 = (Button) findViewById(R.id.get_btn_1);

mBtn1.setOnClickListener(this);

mShowInfo2 = (TextView) findViewById(R.id.second_show);

mBtn2 = (Button) findViewById(R.id.get_btn_2);

mBtn2.setOnClickListener(this);

mShowInfo21 = (TextView) findViewById(R.id.first_show_lin2);

mBtn21 = (Button) findViewById(R.id.get_btn_1_line2);

mBtn21.setOnClickListener(this);

mShowInfo22 = (TextView) findViewById(R.id.second_show_line2);

mBtn22 = (Button) findViewById(R.id.get_btn_2_line2);

mBtn22.setOnClickListener(this);

}

@Override

protected void onStart() {

super.onStart();

//注册EventBus

EventBus.getDefault().register(this);

}

@Override

protected void onStop() {

super.onStop();

//取消EventBus

EventBus.getDefault().unregister(this);

}

//事件1接收者:在主线程接收

public void onEvent(String event){

mShowInfo1.setText(event);

}

//事件2接收者:在主线程接收自定义MsgBean消息

public void onEvent(MsgBean event){

mShowInfo21.setText(event.getMsg());

}

//事件3接收者:在主线程接收

public void onEventMainThread(Integer event) {

mShowInfo2.setText(event+"");

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.get_btn_1:

//事件1发送者:在主线程发送

EventBus.getDefault().post("test!");

break;

case R.id.get_btn_1_line2:

//事件2发送者:在主线程发送自定义MsgBean消息

EventBus.getDefault().post(new MsgBean("type"));

break;

case R.id.get_btn_2:

//事件3发送者:在子线程循环发送

new Timer().schedule(new TimerTask() {

@Override

public void run() {

EventBus.getDefault().post(mCount);

if (mCount >= 3) {

this.cancel();

mCount = 0;

}

mCount++;

}

}, 0, 1000);

break;

}

}

}

xml代码太简单就省略了。

如下运行结果:

45a720e2e03ffe8c5877d8273917150b.png

从上面代码可以看见,当发过来一个消息的时候,EventBus区分onEventxxx被调运通过发送消息的参数类型区分(如:post(new MsgBean(“type”))对应onEvent(MsgBean event),post(“test!”)对应onEvent(String event))。

总结

通过上面基础实战发现,使用EventBus的基本步骤就是如下4步:

定义事件类型(或者不定义)。例如:MsgBean等

定义事件处理方法。例如:onEvent等

注册订阅者。例如:EventBus.getDefault().register(this)

发送事件。例如:EventBus.getDefault().post(new MyEvent())

通过这个例子基本上你就可以上手EventBus框架使用了,也知道了大致基本原理。其实这还是不够,玩意出现bug又很郁闷不知道怎么改,所以下一篇还是老规矩,走读一下EventBus的大致源码,学习下作者的代码思想,同时熟悉EventBus的原理。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐