EventBus3使用实战(二)
EventBus3的使用实战(一)
Sticky Event使用
自己写了一个小例子,两个activity,通过EventBus来传递事件,布局比较简单,代码不贴出来了,
MainActivity:
MainACtivity:
public class MainActivity extends FragmentActivity {
@BindView(R.id.title_tv)
TextView mTextView;
@OnClick(R.id.child_thread_btn)
public void onChildThreadClick(){
new Thread() {
@Override
public void run() {
// EventBus.getDefault().post("hhh");
EventBus.getDefault().postSticky("from MainActivity--child thread post sticky event");
}
}.start();
}
@OnClick(R.id.main_thread_btn)
public void onMainThreadClick(){
EventBus.getDefault().postSticky("from MainActivity--main thread post sticky event");
}
@OnClick(R.id.next_activity_btn)
public void onNextActivityClick(){
startActivity(new Intent(MainActivity.this, SecondActivity.class));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mTextView.setText("sdongwan");
}
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
@Subscribe(sticky = true)
public void onHandleStickyEvent(String str) {
Log.e("thread", "onHandleStickyEvent----MainActivity: main " + str);
}
}
SecondActivity:
public class SecondActivity extends AppCompatActivity {
@OnClick(R.id.post_sticky_btn)
public void onStickyEventClick(){
EventBus.getDefault().postSticky("from SecondActivity--post sticky event");
}
@OnClick(R.id.post_common_btn)
public void onCommonEventClick(){
EventBus.getDefault().post("from SecondActivity--post common event");
}
@OnClick(R.id.last_activity_btn)
public void onLastClick(){
finish();
}
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
ButterKnife.bind(this);
}
@Subscribe(sticky = true)
public void onHandleStickyEvent(String str) {
Log.e("thread", "onHandleStickyEvent------SecondActivity: " + str);
}
}
可以看见MainActivity中onHandleStickyEvent(String str)和SecondActivity中onHandleStickyEvent(String str)事件处理方法都获得了粘性事件;此时,从MainActivity和SecondActivity重复跳动多次,日志会打印出多行事件处理信息,如图:
因为两个Activity间重复跳动多次,导致EventBus.getDefault().register(this)注册多次,每注册一次,EventBus3就会把粘性事件发给事件处理方法,导致重复打印出多行日志;
因为post的是普通事件,没有滞留,事件处理日志只打印一次,MainActivity中收不到普通事件;
这里我们post出的是普通事件,SecondActivity中事件处理机制上加了@Subscribe(sticky = true),也是可以处理普通事件,只是在我们来回切换activity中,日志也只打印一条,因为普通事件没有滞留,重新EventBus.getDefault().register(this),也不会再收到事件;
当然我们在SecondActivity中发送滞留事件,MainActivity也是可以收到的;
提示:EventBus.getDefault().register(this),这句代码的意义是在当前的activity中检索可以响应事件处理(订阅者)的代码,找到类型匹配的事件处理类型,则调用事件处理代码,如果我们在这个例子中,不在MainActivity中注册EventBus,那么我们在MainActivity中post粘性事件,MainActivity中的订阅者就不会被调用;
在上面的例子中,一旦我们post出粘性事件,来回切换activity,都会调用事件处理方法,如果我们一直切换,就会一直调用,这时我们要看看取消事件;
把上面的MainActivity中订阅者事件处理添加几行代码:
@Subscribe(sticky = true)
public void onHandleStickyEvent(String str) {
Log.e("thread", "onHandleStickyEvent----MainActivity: main " + str);
String stickyEvent = EventBus.getDefault().getStickyEvent(String.class);
if(stickyEvent != null) {
EventBus.getDefault().removeStickyEvent(stickyEvent);
}
添加上面取消粘性事件代码后。切换到SecondActivity中,发现不会调用事件处理代码,粘性事件被取消了;
在MainActivity onCreate方法中添加如下代码,自己手动抛出一个异常:
AsyncExecutor.create().execute(
new AsyncExecutor.RunnableEx() {
@Override
public void run() throws LoginException {
// No need to catch any Exception (here: LoginException)
EventBus.getDefault().post(new MyEvent());
throw new LoginException();
}
}
);
添加事件处理代码:
@Subscribe
public void onHandleStickyEvent(MyEvent str) {
Log.e("thread", "onHandleStickyEvent----MainActivity: main " + str);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void handleFailureEvent(ThrowableFailureEvent event) {
// do something
Log.e("thread", "handleFailureEvent: "+event.toString() );
}
运行打印的log如图:
可以看到RunnableEx可以帮助我们处理异常,把异常包裹成ThrowableFailureEvent中,然后post出去,我们可以在订阅者中写相应的异常处理逻辑;
使用android-apt生成索引
在project下的build.gradle添加下面代码
buildscript {
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
在app下的build.gradle添加下面代码:
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile 'org.greenrobot:eventbus:3.0.0'
apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
apt {
arguments {
eventBusIndex ""study.sdw.com.study.myindex(这个根据自己的包名来写,myindex是索引类)""
}
}
点击rebuild,重新build一下,没有错误的话,就可以看到生成的索引类,索引类是在build过程生成的:
点击查看生成的代码:
/** This class is generated by EventBus, do not edit. */
public class myindex implements SubscriberInfoIndex {
private static final Map, SubscriberInfo> SUBSCRIBER_INDEX;
static {
SUBSCRIBER_INDEX = new HashMap, SubscriberInfo>();
putIndex(new SimpleSubscriberInfo(SecondActivity.class, true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onHandleStickyEvent", String.class, ThreadMode.POSTING, 0, true),
}));
putIndex(new SimpleSubscriberInfo(MainActivity.class, true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onHandleStickyEvent", MyEvent.class),
new SubscriberMethodInfo("handleFailureEvent", org.greenrobot.eventbus.util.ThrowableFailureEvent.class,
ThreadMode.MAIN),
}));
}
private static void putIndex(SubscriberInfo info) {
SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
}
@Override
public SubscriberInfo getSubscriberInfo(Class> subscriberClass) {
SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
if (info != null) {
return info;
} else {
return null;
}
}
}
代码里通过索引来保存SubscriberInfo,这样我们就可以在代码配置默认的实例,让它使用索引:
EventBus.builder().addIndex(new myindex()).installDefaultEventBus();