实际项目开发过程中,经常遇到如下场景:不同的应用程序组件的控件间具有一定的相互关联性,其中用户对后者进行的某种操作会引起前者的相应改变。举一个具体的场景:以新浪微博为例,在新浪微博首页好友动态列表页和好友动态详情页(微博正文),对于每个详情页而言,布局基本一致,在详情页点击了个赞,赞的数量增加,同时赞的图标发生了变化,此时返回到列表页,此新浪微博首页上的赞图标以及数量与刚刚详情页的需要保持一致。再举一个例子,对于多个底部导航tab下的资讯类阅读app,在咨询详情页点击了收藏,然后收藏成功,此时回到底部tab中的个人中心,假如个人中心中有我的收藏,同时后面显示的是收藏数量,此时此收藏数量需要同于于刚刚用户所进行的收藏/取消收藏而即时更改数字。显而易见,类似场景需求非常常见。
有时候,当此类需求相对简单时,通过接口以实现回调等方式可以完成,但是当不同组件/控件之间的关系纷繁复杂时,基于接口的方案不仅使得代码非常繁琐,同时是的程序逻辑很混乱,基于此,Android事件总线框架(AndroidEventBus 、EventBus、Otto) ,为此类需求的实现提供了非常方便的方案。
这里我以EventBus框架为例,为大家实现该功能。
什么是EventBus?
EventBus是Android下高效的发布/订阅事件总线机制。作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment,Activity,Service,线程之间传递数据,执行方法。特点是代码简洁,是一种发布订阅设计模式(Publish/Subsribe),或称作观察者设计模式。事件传递既可用于 Android 四大组件间通讯,也可以用户异步线程和主线程间通讯等等。传统的事件传递方式包括:Handler、BroadCastReceiver、Interface 回调,相比之下 EventBus 的优点是代码简洁,使用简单,并将事件发布和订阅充分解耦。
EventBus 负责存储订阅者、事件相关信息,订阅者和发布者都只和 EventBus 关联。
EventBus作为一个消息总线,有三个主要的元素:
compile 'org.greenrobot:eventbus:3.0.0'2.构造发送消息类
public class MainMessage { private String msg; public MainMessage(String msg) { this.msg = msg; } public String getMsg() { return msg; } }
EventBus.getDefault().register(this);解除注册:
EventBus.getDefault().unregister(this);所以完整的代码应该是这个样子:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EventBus.getDefault().register(this); } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); }
EventBus.getDefault().post(messageEvent);
在3.0之前,EventBus还没有使用注解方式。消息处理的方法也只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,分别代表四种线程模型。而在3.0之后,消息处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(beta1默认为PostThread,正式版默认为POSTING),四种线程模型,下面会讲到。 注意,事件处理函数的访问权限必须为public,否则会报异常。
@Subscribe(threadMode = ThreadMode.POSTING) //3.0.0 public void onMessageEventPost(UserEvent event) { //默认方式, 在发送线程执行 } @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEventMain(UserEvent event) { //在ui线程执行 } @Subscribe(threadMode = ThreadMode.BACKGROUND) public void onMessageEventBackground(UserEvent event) { //在后台线程执行 } @Subscribe(threadMode = ThreadMode.ASYNC) public void onMessageEventAsync(UserEvent event) { //强制在后台执行 }
-keepclassmembers class ** { public void onEvent*(**); void onEvent*(**); }
注意: @Subscribe 下的方法必须为public postSticky()发送的粘性消息订阅时必须@Subscribe(sticky = true)否则接收不到 发送的event事件是object类 @Subscribe(priority = 1) 使用时优先级默认为0,然后只有统一模式下设置优先级才有效果,自己看着合理使用