使用EventBus进行组件间通讯

来源:互联网 发布:cocos2dx mac 编辑:程序博客网 时间:2024/05/20 20:20

你是否已经厌倦了在两个Fragment之间传递数据,是否已经厌倦了Service与Activity/Fragment之间的通讯,是否已经厌倦了startActivityForResult中的requestCode, resultCode. 快来试试EventBus吧~

EventBus看名字可以理解成是一个传递事件的公交车,实际上,EventBus也的确是做这个事情。使用的时候,在合适的地方发布一个事件,注册了该事件接收的对象就可以收到通知,进行相应的操作。

EventBus能够很方便的解决上面遇到的麻烦,可以让代码看起来更简洁,写起来更方便,自然也就更少机会的犯错。第一眼看到EventBus的那种解放感已经可以和ButterKnife比肩了。

基本使用,组件之间通讯

这里假设一个上传文件的场景,有一个上传文件的Service: FileUploadService;以及一个显示进度的UI: UploadFragment;以及一个用来传递上传进度的Event: UploadProgressEvent.

先从最简单的UploadProgressEvent看,EventBus并不要求Event对象实现什么接口或者继承什么父类,Event对象可以是任意的POJO. 我们这里用到的UploadProgressEvent只需要有一个progress字段就好了,来标识当前上传的进度,取值范围0-100.

再看一下一个模拟上传的FileUploadService,继承自IntentService,可以默认在新的线程运行,并且可以自动结束。

上面可以看出,每次得到onProgress时候,都会设置一下最新的progress数据,发布一个uploadProgressEvent对象到bus. bus则会很勤快的载着我们的Event到它想去的地方。当然是对应的现实UI的UploadFragment.

在Fragment里面的onStart方法和onStop方法分别进行了EventBus的注册与撤销注册。值得注意的是onEvent方法,该方法接受一个UploadProgressEvent参数。EventBus正是通过这个方法来处理UploadProgressEvent事件的。

看了上面的实例是不是很方便?简单来说,就是A组件与B组件,B组件注册了EventBus之后,A组件发生了事件X,则会通知响应的注册了EventBus的B组件的onEvent(X)的方法处理,so easy~

指定处理线程

默认情况下,onEvent方法会在post(Event)的方法的线程中执行,但是可能会post(Event)是一个非UI线程,而onEvent方法需要更新UI,需要在主线程运行。这时候可以写一个post(Runnable)啥啥啥。但是EventBus提供了一个更简洁的处理方式。

直接使用onEventMainThread方法来处理响应的Event,声明成onEventMainThread的方法会在主机线程运行,这样就可以肆无忌惮的修改UI了。

与onEventMainThread对应的还有onEventBackgroundThread,顾名思义,该方法会在一个Background线程执行,但是这个Background线程是怎么定义的呢?其实Background是指非UI线程,也就是说post(Event)如果是UI线程,那么,onEventBackgroundThread会在另外一个非UI线程执行;如果post(Event)是在一个非UI线程,那么onEventBackgroundThread则和onEvent方法一样,直接在当前线程执行。

除onEvent和onEventBackgroundThread之外,还有一个onEventAsync方法,该方法更简单,不管post(Event)是否是UI线程,onEventAsync都会在一个新的线程执行。

使用Sticky Events

某些时候,我们并不希望发布出来的Event立即被消费掉,而是等到时机成熟。比如说,在一个详情页点赞之后,产生一个VoteEvent,VoteEvent并不立即被消费,而是等用户退出详情页回到商品列表之后,接收到该事件,然后刷新Adapter等。其实这就是之前我们用startActivityForResult和onActivityResult做的事情。

那么怎么用EventBus来模拟这样的情况呢?这就需要另外一个强大的机制,Sticky Event.

和普通的Event不同,当发布一个Sticky Event,需要使用postSticky方法:

上面的代码发布了一个点赞的Sticky Event.


上面的代码则是在对应的列表页面,onStart方法调用了EventBus的registerSticky方法,该方法在每次执行的时候,都回去查询一次Sticky Event,并调用响应的方法处理。本例中,当列表页面第一次显示的时候,是没有Sticky Event的,所以registerSticky不会触发任何事件;而当列表页面是由详情页退出后显示出来的话,registerSticky会触发在详情页postSticky的VoteEvent,而触发onEventMainThread(VoteEvent)方法,以达到onActivityResult方法的效果。

除了registerSticky方法来触发Sticky Event之外,我们还可以通过getStickyEvent方法来获取响应的Sticky Event来进行处理。比如:

我们可以在每次的onResume方法里面检查EventBus里面是否有VoteEvent的Sticky Event,从而进行处理。

总之,EventBus极大的减轻了我们各种组件之间的通讯复杂度,也大大减少了使用Activity Result的麻烦。真实值得极力推荐。

0 0
原创粉丝点击