EventBus 3.0使用详解源码分析(一)
目录
-
Eventbus前言
在项目开发中,总会遇到组件和组件之间,组件和线程、service之间进行通信,比如activity和多个fragment通信。android 原生也提供了一下方法,我们经常用的,有广播,handler,写回调方法以及intent。这些都可以解决通信需求,但是这样耦合度比较高,并且代码量也比较大。今天介绍的eventbus可以很方便的解决这些问题。
-
EventBus简介
首先容许我盗一张图:
大致意思是说,eventbus能够简化组件间通信,代码更简单,有效分离了时间发送方和接收方,并且有很多应用集成了eventbus安全和性能应该有保障。但是eventbus也有一个不太便利的地方。如果事件种类比较多的情况。那么观察者需要注册的函数就会变得很多。这样就会带来一些不便,再有就是后来者接手项目,不熟悉代码的情况下,比较难找到他的来龙去脉。
最后单独说一下他的基本原理: eventbus就是一个典型的观察者模式的使用,通过publisher发布消息,然后Subscriber接收消息。然后进行处理。整个结构大致有三个模块需要注意:
- 1 event:发布者发布的消息,可以是继承自Object的任意类。
- 2 publisher:事件的发布者,可以在任意线程发布消息,一般通过EventBus.getDefault().post(Event)就可以发布。
- 3 Subscriber: 事件的接收者,通过register,unregister函数来注册成为观察者。处理事件的方法要通过注解@Subscribe()中的参数来标明处理事件的线程模型,优先权,以及是否是黏性广播。
在观察者类中处理消息的函数要通过注解@Subscribe(ThreadMode,isSticky,priority)来指定处理消息的一些基本信息,注解共有三个参数。其中ThreadMode表示在哪个线程里面处理收到的消息,它有四种方式:
- 1 POSTING, 默认参数,哪个线程发布的消息,就在哪个线程里面处理消息。
- 2 MAIN, 表示在主线程处理消息,就是ui线程,不能进行耗时操作。
- 3 BACKGROUND, 表示后台线程处理,不能进行ui操作,如果发布消息在ui线程中发布,那会重启一个线程,如果是后台线程,就在发布消息的线程处理。
- 4 ASYNC ,无论发布线程是哪个,都会重新开一个线程处理。可以进行耗时操作。
sticky 这个参数表示是否是黏性广播,默认false,非黏性广播当发布者发布消息的时候,没有注册的开发者不能收到任何消息,如果注册为黏性,那么当观察者注册成功之后,会收到最后一条发布的广播。
priority表示处理的优先级。默认为0.
-
EventBus使用
首先添加依赖:
implementation 'org.greenrobot:eventbus:3.1.1'
如果需要混淆要添加一下代码:
-keepattributes *Annotation*
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
简单写一个消息类:
public class MessageEvent extends MessageObject{
String message;
int id;
public MessageEvent(String msg,int id){
super(msg);
this.message = msg;
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
eventbus可以用于activity,fragment,service等控件,其注册方式都一样,本文用activity做例子,发送消息的activity如下:
public class MainActivity extends Activity {
@BindView(R.id.mainclick)
Button mainClick;
@BindView(R.id.threadclick)
Button threadClick;
WidgetBroadcastReceiver mReceiver;
RxPermissions rxPermissions;
@SuppressLint("HandlerLeak")
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
postMsgMain();
postMsgThread();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mReceiver = new WidgetBroadcastReceiver();
ButterKnife.bind(this);
mainClick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent ii = new Intent(MainActivity.this, EventBusActivity.class);
startActivity(ii);
mHandler.sendEmptyMessageDelayed(1, 1000 * 5);
}
});
}
private void postMsgMain(){
EventBus.getDefault().post(new MessageObject("this is default"));
Log.e("tag"," ****main id===="+Thread.currentThread().getId());
}
private void postMsgThread() {
new Thread(new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(new MessageEvent("from thread",1 ));
Log.e("tag","*thread id===="+Thread.currentThread().getId());
}
}).start();
}
}
点击按钮延后5,6秒通过EventBus.getDefault().post()分别发送一个主线程消息和后台消息。
public class EventBusActivity extends Activity {
@BindView(R.id.content_text)
TextView contentView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_bus);
ButterKnife.bind(this);
//注册观察者
EventBus.getDefault().register(this);
}
/**
* 处理消息,只能是一个参数,通过参数识别处理哪个消息。发送的消息和参数匹配才会处理。
* @param me
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageObject me) {
String content = me.getObject();
contentView.setText(content);
Log.e("tag", "the MAIN msg id==="+Thread.currentThread().getId());
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessageEvent1(MessageEvent me) {
String content = me.getMessage();
Log.e("tag", "the POSTING msg===" + me.getMessage()+Thread.currentThread().getId());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent2(MessageEvent me) {
String content = me.getMessage();
Log.e("tag", "the BACKGROUND msg===" + me.getMessage()+Thread.currentThread().getId());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessageEvent3(MessageEvent me) {
String content = me.getMessage();
Log.e("tag", "the ASYNC msg===" + me.getMessage()+Thread.currentThread().getId());
}
@Override
protected void onDestroy() {
super.onDestroy();
if(EventBus.getDefault().isRegistered(this)) {
//取消注册
EventBus.getDefault().unregister(this);
}
}
}
在这里接收处理消息。在这个例子中通过打印线程id确认执行属性。日志如下:
EventBus的基本用法就是这样,接下来我会分析源码来解释eventbus的运行机制。
EventBus的github地址:
上一篇: PHP中file_exists()判断中文文件名无效的解决方法
下一篇: 经典算法学习直接选择排序
推荐阅读
-
vuex 源码分析(一) 使用方法和代码结构
-
android事件总线EventBus3.0使用方法详解
-
Mac下使用IntelliJ IDEA导入Spring源码-Spring源码分析系列(一)
-
mybatis的使用及源码分析(一) mybatis介绍以及原生Mybatis项目搭建
-
荐 Vue3.0 源码分析(一):响应式模块 reactivity
-
分析easyswoole3.0源码,服务启动为例(一)
-
Elasticsearch源码分析之一——使用Guice进行依赖注入与模块化系统
-
EventBus 3.0使用详解源码分析(一)
-
依赖注入框架 ----Dagger2 使用详解及源码分析
-
Lucene3.0源码分析(一) 在Eclipse/MyEclipse上建立Lucene3.0工程