EventBus框架在Android多Pane(Fragment)中的应用
通常多pane的设计中,比如Fragment A是个Headline,Fragement B是detail,那么B通常需要实现A的点击事件的接口,这样子的话,两个fragment就高耦合了,而且需要在Fragment A中编写一个interface,如果Fragment很多,情景更复杂些,就乱了。
这里可以使用EventBus这个框架,一个典型的发布者-订阅者模式。具体可以参考:
使用方法大致如下:
这个例子来源于Android Developers的一个典型的多Fragment的例子,左边Fragment是HeadlineFragment,含有很多标题的listview,右边是DetailFragment,点击左边Fragment中一项会刷新右边的Fragment。
a. 首先定义自己的Event,这里其实是随便写个类,例子中Headline需传一个点击时候的listview的position给Detail fragment,所以可以写个包装int类型的MessageEvent:
public class MessageEvent { public int position; public MessageEvent(int position) { this.position = position; } }
b. 在订阅者(即Detail fragment或者说fragment B)中,onstart和onstop要注册/解注册:
//DetailFragment.java
@Override public void onStart() { super.onStart();; EventBus.getDefault().register(this); } @Override public void onStart() { super.onStart(); setNewsCategory(0); EventBus.getDefault().register(this); }
c. 在订阅者(即Detail fragment或者说fragment B)中,写一个名字叫onEvent的函数,带回来的参数是MessageEvent类型,这个函数即被调用的方法,等待Headline传过来包装了position数据的MessageEvent对象
//DetailFragment.java
public void onEvent(MessageEvent event){ int index = event.positioin; // do something using index,比如刷新文章内容 }
d. 在发布者(即Headline Fragment或者说Fragment A)中,在合适的地方执行post方法,即发布出去这个MessageEvent,这里即在HeadLineFragment的listview被点击的回调中发送post:
//HeadLineFragment.java
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
EventBus.getDefault().post(new MessageEvent(position)); }
这样子,DetailFragment的onEvent方法就会被调用,含有position的MessageEvent也就被传了过去,随之DetailFragment根据拿到的position来刷新界面。
大功告成,这里可以发现两个fragment没有写任何的interface也没implements任何的接口,也不用实例化一个listenser并且执行所谓的setonlistener。
这里的内部流程大致是,EventBus在某个组件中注册的时候回记录下这个组件里面的onEvent函数,一个应用中可能有多个onEvent函数等待被调用,这里即通过onEvent函数的参数类型和个数来区别。
使用时需要注意一个问题,这里EventBus是通过java反射机制来找到这个onEvent方法的,所以打包的时候若需要混淆的话千万记住不要混淆onEvent这个函数,可以在proguard文件中添加:
-keepclassmembers class ** { public void onEvent*(**); }
关于EventBus更多使用方法以及源码可以参考