Android EventBus3.0的使用
1.前言
EventBus是一款轻量级的事件发布/订阅框架。主要是用于各个组件或是线程之间的数据传递。将事件的发送者和接受者分离开来,避免了复杂的和易错的依赖关系。既然听起来这么美好,那么我们就开始使用它吧。
第一件事永远别忘了,就是配置 build.gradle
。
compile 'org.greenrobot:eventbus:3.0.0'
2.基本使用及示例
由于EventBus采用了观察者的设计模式,如果直接看使用方法有点不太好理解,建议可以先去了解一下观察者模式。那么,就直接进入正题吧。
① 在接收事件的地方进行注册。
EventBus.getDefault().register(this);
② 创建一个EventBus消息类,用于存放一些数据,有些类似我们JavaBean类。
public class MessageEvent {
private String message;
public MessageEvent(String message) {
this.message = message;
}
}
③ Post发送事件
EventBus.getDefault().post(messageEvent);
④ 接收事件,方法名可进行自定义,但是注解 @Subscribe
必须有,并且权限必须为public。
@Subscribe
public void abc(MessageEvent messageEvent) {
...
}
⑤ 取消注册,有注册就必须有解注册,并且我们一般在 onDestroy
里执行取消注册的操作。
EventBus.getDefault().unregister(this);
那么,我们大致了解了EventBus的使用流程之后,就用一个小示例来加深一下理解吧。这里我就使用Activity与Fragment的通信作为例子吧。
public class FragmentEvent {
private String text;
FragmentEvent(String text){
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
同样是先创建消息类,其他代码比较简单,就只贴上重要的部分吧。
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button button_post;
private EditText et;
private EVFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
button_post = (Button) findViewById(R.id.button_post);
et = (EditText) findViewById(R.id.et);
button_post.setOnClickListener(this);
fragment = new EVFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.content, fragment);
transaction.commit();
}
@Override
public void onClick(View v) {
String message = et.getText().toString();
if(TextUtils.isEmpty(message)) {
message = "没输入哦!!";
}
EventBus.getDefault().post(new FragmentEvent(message));
}
@Subscribe
public void onFragmentEvent(FragmentEvent event) {
fragment.setTv(event.getText());
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
应该不是很难,就不废话了,直接来看下结果吧。
3.线程模型
EventBus有四种线程模型,它们分别是POSTING、MAIN、BACKGROUND、ASYNC。在处理事件的函数中必须指定一个线程模型,那么,为什么上面的实例中没有指定呢?是因为默认的情况下,指定的是POSTING。可以一起来看下它们四个到底是什么含义。了解之前请记住一点,主线程不能执行耗时操作,不能在子线程中更新UI。
① POSTING:发送和接收事件在同一线程中,并且避免执行耗时操作。
② MAIN:无论发送事件在哪个线程,都会在UI主线程中接收事件,同样不能执行耗时操作。
③ BACKGROUND:事件在UI主线程中发送,在新线程中接收;事件在子线程中发送,则在该线程中接收。当然,不能进行UI的更新。
④ ASYNC:无论发送事件在哪个线程,都会在新建的线程中接收事件。同样不能进行UI的更新。
文字描述可能有点看的有些混乱,那么就做个表方便记忆。
线程模型 | 主线程中发送事件 | 子线程中发送事件 |
---|---|---|
POSTING | 主线程 | 子线程 |
MAIN | 主线程 | 主线程 |
BACKGROUND | 新子线程 | 子线程 |
ASYNC | 新子线程 | 新子线程 |
当然,我就拿一个线程模型ASYNC出来写个小例子,其余的大家可以自己尝试下。
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_main:
Log.i("MAIN_POST", Thread.currentThread().getName());
EventBus.getDefault().post(new MessageEvent(""));
break;
case R.id.button_thread:
new Thread(new Runnable() {
@Override
public void run() {
Log.i("THREAD_POST", Thread.currentThread().getName());
EventBus.getDefault().post(new MessageEvent(""));
}
}).start();
break;
}
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessageEvent(MessageEvent event) {
Log.i("ASYNC", Thread.currentThread().getName());
}
代码还是比较好理解的,直接来看结果吧。
可以看到无论事件是从主线程还是子线程中发出来的,都是新开了一个线程来处理事件,这也就论证了上面的结论。
4.黏性事件
黏性事件的用法上与普通的很类似,区别在于,一要将sticky的值设为true,二是使用 postSticky()
方法来发送事件。同样它也有两个特点,请记住,第一个是在发送事件之后再订阅也能收到该事件,第二个是只能接收到最近的一条信息。
口说无凭,还是用个例子来验证下。
@Override
public void onClick(View v) {
EventBus.getDefault().unregister(this);
for(int i = 0; i < 5; i++) {
EventBus.getDefault().postSticky(new FragmentEvent(i + ""));
}
EventBus.getDefault().register(MainActivity.this);
}
@Subscribe(sticky = true)
public void onFragmentEvent(FragmentEvent event) {
Log.e("RESULT", event.getText());
}
再来一起看下结果。
可以清楚的看到,总共发送了5次黏性事件,都显示没有订阅者,而发送完之后再进行注册,收到了最后一次发送的消息。
5.优先级
如果考虑到要使用优先级,那么只需要将priority的值进行设置就行了,默认情况下是为0的。priority的值越大,优先级也就越高,也就意味着最先收到发布的事件。当然,优先级的对比也是有前提的,就是必须为同一线程模型的情况下。同样,一个小例子就能说明这一切。
@Override
public void onClick(View v) {
EventBus.getDefault().post(new FragmentEvent("priorityPK"));
}
@Subscribe(threadMode = ThreadMode.MAIN, priority = 1)
public void onFragmentEvent(FragmentEvent event) {
Log.e("PRIORITY1", event.getText());
}
@Subscribe(threadMode = ThreadMode.MAIN, priority = 100)
public void onFEvent(FragmentEvent event) {
Log.e("PRIORITY100", event.getText());
}
由于代码比较简单,就直接看结果了。
6.索引配置
如果一定要使用EventBus3.0的话,建议还是进行以下配置,这样效率会比较高。
首先,在Project下的build.gradle文件中添加:
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
接着,在app下的build.gradle文件中添加:
apply plugin: 'com.neenbedankt.android-apt'
apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
apt {
arguments {
eventBusIndex "com.lc.MyEBIndex"
}
}
配置完后进行Rebuild,会生成如图的一个文件,该文件也就是上面配置的,可以自行命名。
最后呢,将生成的索引给默认的EventBus对象进行设置就行了。
apt {
arguments {
eventBusIndex "com.lc.MyEBIndex"
}
}
那么,EventBus就学习完了,可以睡觉了。
7.总结
略!!!
参考: