EventBus
由greenRobot公司开发, 目的是简化开发中的事件传递.
优点
- 注释没有使用反射, 在编译时完成注解解析不影响程序性能
- 代码简单, 使用注解简化了代码量,代码逻辑更加清晰
- 简化组件通讯, 在不同的activity等组件之间方便的传递事件
- 优化线程传递, 在不同的线程处理事件(例如ui或者耗时操作)不再需要考虑线程切换使用AsyncTask之类的方法
演示
EventBus由三部分组成: 事件类, 注册事件订阅者, 发送事件
添加依赖
compile 'org.greenrobot:eventbus:3.0.0'
定义事件类
“`java
public class EventTest {String message; public EventTest(String message) { this.message = message; }
}
“`注册事件订阅者
“`java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);// 创建单例对象注册此activity EventBus.getDefault().register(this); } /**
- 在EventBus发送事件时被调用
- 方法名随意, 只要加上@Subscribe注释即可
* - @param eventTest 接受被发送的事件类
*/
@Subscribe
public void casualName(EventTest eventTest) {
Toast.makeText(this, eventTest.message, Toast.LENGTH_SHORT).show();
}
“`
发送事件
// 该方法可以在任意类中被使用, 向被注册的类发送事件 EventBus.getDefault().post(new EventTest(5));
Sticky粘性事件
如果用上面的方法直接向下一个界面的activity发送事件, 将会出现找不到订阅者的警告. 但是第二次进入又会执行事件订阅者, 但是依然无法在订阅者内修改任何UI, 因为收到的是上一个被销毁的界面的事件.
为了解决这种发送事件和接收事件无法达到匹配的问题就得使用EventBus的粘性事件
发送粘性事件
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
接收粘性事件
@Override
public void onStart() {
super.onStart();
// 这一句必须在register方法之前执行, 否则在订阅者中使用这个控件会导致空指针, 但不会造成程序挂掉
mViewById = (TextView) findViewById(R.id.textView);
EventBus.getDefault().register(this);
}
// UI 更新必须在主线程
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN) // 注意Subsctibe的参数变更
public void onEvent(MessageEvent event) {
textField.setText(event.message);
}
要注意的是在订阅者中操作的数据必须在register注册事件之前初始化完成
直接得到事件类
如果只是想得到事件类还可以使用更加方便的获取方式
EventTest eventTest = EventBus.getDefault().getStickyEvent(EventTest.class);
线程通讯
EventBus能做到自动处理线程切换, 只需要使用不同的线程模式
即可实现订阅者在不同的线程执行操作, 如果涉及到子线程, 将开启线程池
.但是如果是在子线程发送的事件将不会开启线程池, 且只有写在主线程的订阅者才是能接收事件的订阅者
线程模式
- POSTING
- MAIN
- BACKGROUND
- ASYNC
/**
* 默认线程模式, 和@Subscribe一样, 在发送者所在线程执行事件
*
* @param eventTest 事件类
*/
@Subscribe(threadMode = ThreadMode.POSTING)
public void defaultEvent(EventTest eventTest) {
Log.i("日志", "defaultEvent >>> " + Thread.currentThread().getName());
}
/**
* 在子线程执行事件, 如果发送者在子线程将不会新建子线程
*
* @param eventTest
*/
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void backgroundEvent(EventTest eventTest) {
Log.i("日志", "backgroundEvent >>> " + Thread.currentThread().getName());
}
/**
* 无论发送者在子线程亦或主线程都将会新建一个子线程执行事件
*
* @param eventTest
*/
@Subscribe(threadMode = ThreadMode.ASYNC)
public void AsyncEvent(EventTest eventTest) {
Log.i("日志", "MainActivity.AsyncEvent_68 >>> " + Thread.currentThread().getName());
}
只需要使用不同的订阅者注解即可在不同的线程之间切换事件传递