安卓开发笔记——探索EventBus

一、关于EventBus:java

组件通信在Android开发中是不可避免的,随着业务需求的复杂化,代码中须要咱们去处理的业务逻辑难度也不断增大。例如多个Fragment之间的数据传递,Service与Activity、Fragment之间的通信,BroadCast与Activity、Fragment之间的通信,各类startActivityForResult的使用,繁杂的操做令咱们所厌倦,在GitHub上找了下解决方案,发现了一个不错的开源库EventBus,相信不少作过Android开发的朋友都或多或少对此有所了解。android

  EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优势是开销小,代码更优雅。以及将发送者和接收者解耦。git

  这是EventBus在GitHub上的开源库地址:https://github.com/greenrobot/EventBusgithub

  EventBus的大致关系是这样的:订阅者(Subscriber)经过订阅事件(Event)到总线,事件发布者(Publisher)发布事件(Event)到总线被订阅者(Subscriber)接收,其实说白了就是软件设计模式里的观察者模式。EventBus在使用的时候就是在合适的地方发布一个事件,使得注册了该事件接收的对象就能够收到通知,进行相应的操做。设计模式

二、初探EventBus:app

  文绉绉的文字描述使人厌烦,直接上代码说话吧,先来看下要实现的效果:ide

  

  看似很简单的效果,点击按钮跳转界面,利用Intent发送一个消息,而后TextView接收显示。这是传统上的作法,若是真是这样作,那么写这篇文章的就彻底没意义了。其实这里就是利用到了EventBus,并无用到Intent来传递消息。函数

  先来看下具体的代码(记得添加EventBus的引用),而后我再分部来解析:post

 1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
 2 
 3 import android.content.Intent;
 4 import android.os.Bundle;
 5 import android.support.v7.app.AppCompatActivity;
 6 import android.view.View;
 7 import android.widget.Button;
 8 import android.widget.TextView;
 9 
10 import de.greenrobot.event.EventBus;
11 
12 public class MainActivity extends AppCompatActivity {
13 
14     private Button mBt_1;
15     private TextView mTv_1;
16 
17     @Override
18     protected void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.activity_main);
21         //注册绑定EventBus
22         EventBus.getDefault().register(this);
23 
24         initView();
25         initAction();
26 
27     }
28 
29     private void initAction() {
30         mBt_1.setOnClickListener(new View.OnClickListener() {
31             @Override
32             public void onClick(View v) {
33                 startActivity(new Intent(MainActivity.this, SecondActivity.class));
34             }
35         });
36     }
37 
38     private void initView() {
39         mBt_1 = (Button) findViewById(R.id.bt_1);
40         mTv_1 = (TextView) findViewById(R.id.tv_info1);
41     }
42 
43 
44     //接收所订阅的消息
45     public void onEventMainThread(MyEvent myEvent) {
46         if (myEvent.getInfo()!=null) {
47             mTv_1.setText(myEvent.getInfo());
48         }
49 
50     }
51 
52 
53     @Override
54     protected void onDestroy() {
55         super.onDestroy();
56         //解绑EventBus
57         EventBus.getDefault().unregister(this);
58     }
59 }
MainActivity.java
 1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
 2 
 3 import android.os.Bundle;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.view.View;
 6 import android.widget.Button;
 7 import android.widget.Toast;
 8 
 9 import de.greenrobot.event.EventBus;
10 
11 public class SecondActivity extends AppCompatActivity {
12 
13     private Button mBt_2;
14 
15     @Override
16     protected void onCreate(Bundle savedInstanceState) {
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.activity_second);
19         initView();
20         initAction();
21 
22     }
23 
24     private void initAction() {
25         mBt_2.setOnClickListener(new View.OnClickListener() {
26             @Override
27             public void onClick(View v) {
28                 Toast.makeText(SecondActivity.this,"消息已发送",Toast.LENGTH_SHORT).show();
29                 EventBus.getDefault().post(new MyEvent("我是被发送过来的消息"));
30 
31             }
32         });
33     }
34 
35     private void initView() {
36         mBt_2 = (Button) findViewById(R.id.bt_2);
37     }
38 
39 
40 }
SecondActivity.java
 1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
 2 
 3 /**
 4  * Created by Lichenwei
 5  * Date: 2015-10-11
 6  * Time: 18:23
 7  */
 8 public class MyEvent {
 9 
10     private String info;
11 
12     public MyEvent(String info) {
13         this.info = info;
14     }
15 
16     public String getInfo() {
17         return info;
18     }
19 
20     public void setInfo(String info) {
21         this.info = info;
22     }
23 }
MyEvent

  上面的代码很简单,这里只是抛砖引玉并不作太多复杂的操做,你们能够根据本身的项目需求来添加对应的代码。优化

三、解析代码:

一、注册EventBus: 

  在添加EventBus的引用后,咱们就能够对任意类进行注册绑定和解绑EventBus事件,注册方法和反注册方法很简单,在上面的代码中就能够看出来了,分别是register和unregister,这里的EventBus.getDefault是获取到EventBus实例的意思(单例)。

1 //注册绑定EventBus
2 EventBus.getDefault().register(this);
3 //解绑EventBus
4 EventBus.getDefault().unregister(this);

 

二、EventBus事件:

  EventBus很灵活,它对事件不进行任何的限制,也不须要继承或者实现任何类或者接口,能够是任意类型的实体类,比如上面代码提到的MyEvent。

 

三、EventBus事件发布者:

  有了事件以后,咱们就能够对事件进行发布,而后能够被订阅这个事件的全部订阅者所接收。发送事件很简单,有两种方法post与postSticky:

1 //当即发送事件 
2 EventBus.getDefault().post(Object event);
3 //延迟发送事件
4 EventBus.getDefault().postSticky(Objet event);

 

四、EventBus事件订阅者:

  EventBus的事件订阅者能够是任何已经进行注册EventBus的类,订阅者的数量是没有上限的(很重要,下文会提到),这里的订阅有4种方法,这里都是由onEvent开头的,有着必定的区别:

  一、onEvent:

  若是使用onEvent做为订阅函数,那么该事件在哪一个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在onEvent方法中不能执行耗时操做,若是执行耗时操做容易致使事件分发延迟。
  二、onEventMainThread:

  若是使用onEventMainThread做为订阅函数,那么不论事件是在哪一个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是很是有用的,由于在Android中只能在UI线程中跟新UI,因此在onEvnetMainThread方法中是不能执行耗时操做的。
  三、onEventBackground:

  若是使用onEventBackgrond做为订阅函数,那么若是事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,若是事件原本就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
  四、onEventAsync:

  使用这个函数做为订阅函数,那么不管事件在哪一个线程发布,都会建立新的子线程在执行onEventAsync。

1  public void onEvent(Object event) {}
2  public void onEventMainThread(Object event) {}
3  public void onEventBackgroundThread(Object event) {}
4  public void onEventAsync(Object event) {}

  介绍完EventBus里的全部角色后,咱们来理一理订阅/被订阅流程:

  首先,要想成为事件订阅者须要先对EventBus进行注册绑定,而后在本类须要去写一个以onEvent开头的方法来接收处理消息事件,再来咱们须要一个自定义的事件可让事件的发布者发布,让事件的订阅者接收。事件的发布能够经过post方法或者是postSticky方法发布。

 

四、EventBus所带来的一些方便之处:

  EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优势是开销小,代码更优雅。以及将发送者和接收者解耦。这是咱们在文章开头所介绍过的,这里就很少说了,说几个在实际开发中所运用到的地方。

  例如:

  一、当某个页面的某些值发生变化的时候,须要去同时去更改多个页面相对应的值,这时候只要这些类注册订阅了该事件,那么咱们就能够很轻松经过post发送消息来进行通信。

  二、某些时候,咱们并不但愿发布出来的Event当即被消费掉,而是等到时机成熟。好比说,在一个详情页点赞以后,产生一个事件,这个事件并不当即被消费,而是等用户退出详情页回到商品列表以后,接收到该事件,而后刷新Adapter等。其实这就是以前咱们用startActivityForResult和onActivityResult作的事情。这里咱们就能够利用postSticky来实现这样的机制。

  总之,EventBus极大的减轻了咱们各类组件之间的通信复杂度,也大大减小了使用ActivityForResult的麻烦。真实值得极力推荐。

 

五、理解EventBus

  从源码中咱们能够知道,当咱们在类中注册绑定EventBus的时候,它会去扫描当前类并记录下全部已onEvent开头的方法,存放在一个Map<Key,Value>中,在事件经过post发布以后,EventBus会根据post中实参的类型,去Map中查找对应的方法,并找到了对应的Thread,最终利用Java的反射机制去执行咱们的方法。

  onEventMainThread表示这个方法会在UI主线程执行。

  onEventPostThread表示这个方法会在当前发布事件的线程中执行。

  BackgroundThread表示若是在非UI主线程发布的事件,则直接执行,和发布在同一个线程中。若是在UI线程发布的事件,则加入后台任务队列,使用线程池一个接一个调用。

  Async 加入后台任务队列,使用线程池调用,注意没有BackgroundThread中的一个接一个。

 

做者:李晨玮
出处:http://www.cnblogs.com/lichenwei/本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文连接。正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,往后必有一番做为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不许,你也好回来找我!

相关文章
相关标签/搜索