android 技术之EventBus

来源:互联网 发布:淘宝瑞联代购是正品吗 编辑:程序博客网 时间:2024/04/29 08:34

1、背景介绍

如果你学习过设计模式,那么当想通知其他组件某些事情发生时你一定会使用观察者模式。好了,既然能想到这个设计模式,那么就来看一个屌爆天的Android开源框架EventBus。主要功能是替代IntentHandlerBroadCastFragmentActivityService、线程之间传递消息。他的最牛逼优点是开销小,代码简洁,解耦代码。

2、EventBus的概念和理解

EventBus**是一个Android端优化的publish/subscribe消息总线,简化了应用程序内各组件间、组件与后台线程间的通信。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通过Listener通信,这些需求都可以通过**EventBus**实现。

作为一个消息总线,有三个主要的元素:

  • Event:事件
  • Subscriber:事件订阅者,接收特定的事件
  • Publisher:事件发布者,用于通知Subscriber有事件发生
    总之,就是通过订阅和发布,订阅发布者的信息。并完成通信的操作。


(1) Event 顾名思义就是事件的意思:它代表的的是任意类型的对象
(2)Subscriber   是以约定的onEvent为开头的函数,四个分别为:

onEvent:使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。

onEventMainThread:无论事件在哪个线程发布出来的,始终在UI线程中执行订阅事件的操作。

onEventBackground:无论事件在哪个线程发布出来的,始终在工作线程中执行订阅事件的操作。

onEventAsync:使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行

(3)发布者,格式是: EventBus.getDefault().post(object);


3、如何使用EventBus

官方给出的使用方式是:

1Define events://定义事件public class MessageEvent { /* Additional fields if needed */ }

2Prepare subscribers//注册订阅者Register your subscriber (in your onCreate or in a constructor): eventBus.register(this);

3Declare your subscribing method://订阅事件的动作@Subscribe public void onEvent(AnyEventType event) {/* Do something */};

4Post events://发布者发送事件eventBus.post(event);


(1) 注册EventBus  

(2)注销EventBus  

(3) 发布EventBus  

(4)订阅EventBus  


4、Demo项目的实战

接下来做一个借着注册的界面实现以下操作,实际并不是用于注册(请注意了,注意思想就好)!

(1) 首先记得加上jar包 在Android studio 的 app下的 build 加上compile'org.greenrobot:eventbus:3.0.0'

代码块:

publicclassMainActivity extends AppCompatActivity {  

private TextView tv1,tv_status;  

@Override  

protectedvoidonCreate(Bundle savedInstanceState) {  

super.onCreate(savedInstanceState);  

setContentView(R.layout.activity_main);  

EventBus.getDefault().register(this);//在当前界面注册一个订阅者  // 1**

tv1=(TextView)findViewById(R.id.tv);  

tv_status=(TextView)findViewById(R.id.tv_status);  

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {  

@Override  

publicvoidonClick(View view) {  

Intent intent =new Intent(getApplicationContext(),  

LoginActivity.class);  

startActivity(intent); } }); }  

@Subscribe//订阅事件FirstEvent  

publicvoidonEventMainThread(LoginSuccessdEvent event){ // 2**

String msg=event.getMsg();  

tv_status.setText("已登录,当前账号"+msg);//获取事件中传递的参数  

Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); }  

@OverrideprotectedvoidonDestroy() {  

super.onDestroy();  

EventBus.getDefault().unregister(this);//取消注册 }} //3**


以上方法中 1** 的 当你需要在哪个界面订阅的时候都需要在里面注册   (不过还有一种情况是先拿到事件,然后在订阅  ,这就是所谓的粘性事件,,,感兴趣的可以自己查查)

2**   当需要订阅的时候 都需要选择 Subscriber   约定的onEvent为开头的四种函数其中的一种,然后参数就是上面说的event  他可以是任何对象

3**  既然注册了,就需要注销 ,防止内存溢出。这个就不用多说了


(2) 发布事件

其实就是很简单的一局代码:EventBus.getDefault().post(new 这里就是你的自己定义的事件); 

(3) 定义事件

随便举例定义的事件,实际按各位需要的定义事件:

 

publicclass LoginSuccessdEvent {  

private String msg;  

publicLoginSuccessdEvent(String msg) {

//事件传递参数  

this.msg = msg; }  

public String getMsg() {

//取出事件参数  

return msg; }  

publicvoidsetMsg(String msg) {  

this.msg = msg;  

}}




EventBus的基本使用官方参考:https://github.com/greenrobot/EventBus
另外在推荐 一篇和好的文章 :http://www.cnblogs.com/angeldevil/p/3715934.html



4EventBus的使用方向

对比Java监听器接口(Listener Interfaces

Java中,特别是Android,一个常用的模式就是使用”监听器(Listeners)”接口。在此模式中,一个实现了监听器接口的类必须将自身注册到它想要监听的类中去。这就意味着监听与被监听之间属于强关联关系。这种关系就使得单元测试很难进行开展。Jake Wharton在他的《使用Otto解耦Android应用间通信》这篇文章中很好地阐述了这个问题,在此我就不进行展开了。

对比本地广播管理器(LocalBroadcastManager

另一项技术就是在组件间通过本地广播管理器(LocalBroadcastManager)进行消息的发送与监听。虽然这对于解耦有很好的帮助,但它的API不如EventBus那样简洁。此外,如果你不注意保持Intent extras类型的一致,它还可能引发潜在的运行时/类型检测错误。

考虑下面的应用场景:

组件A执行一个批量异步数据库更新操作。当成功完成时,它发送一条通知告诉更新了多少条记录。发生错误时,发送一条通知包含了错误信息。

组件B则需要知道到更新是否完成和更新了多少条记录,以及是否有错误发生和错误信息。

使用LocalBroadcastManager,最简单的代码大概如下面所示。

组件A

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

// when update completes successfully

Intent intent = new Intent();  

intent.setAction(FILTER_ACTION_UPDATE_SUCCESS);  

intent.putExtra(EXTRA_COUNT, count);  

LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);

 

...

 

// when there is an error

Intent intent = new Intent();  

intent.setAction(FILTER_ACTION_UPDATE_ERROR);  

intent.putExtra(EXTRA_ERROR_MSG, error.getMessage());  

LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);

组件B:

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

IntentFilter updateSuccessFilter = new IntentFilter(FILTER_ACTION_UPDATE_SUCCESS);  

BroadcastReceiver updateSuccessReceiver = new BroadcastReceiver() {  

    @Override

      public void onReceive(Context context, Intent intent) {

      int updateCount = intent.getIntExtra(EXTRA_COUNT, -1);

      // TODO - do something with the count

    }    

};

 

IntentFilter updateErrorFilter = new IntentFilter(FILTER_ACTION_UPDATE_ERROR);  

BroadcastReceiver updateErrorReceiver = new BroadcastReceiver() {  

    @Override

      public void onReceive(Context context, Intent intent) {

      String errorMsg = intent.getStringExtra(EXTRA_ERROR_MSG);

      // TODO - display error message or similar

    }    

};

 

...

 

getContext().registerReceiver(updateSuccessReceiver, updateSuccessFilter);  

getContext().registerReceiver(updateErrorReceiver, updateErrorFilter);

 

...

 

getContext().unregisterReceiver(updateSuccessReceiver);  

getContext().unregisterReceiver(updateErrorReceiver);

使用EventBus,同样功能实现可以表示如下。(注:此例中我使用的是我的EventBus实现,参见Green RobotEventBus。)

Event类:

Java

 

1

2

3

4

5

6

7

public class UpdateCompleteEvent {  

  public final int count;

 

  UpdateCompleteEvent(int count){

    this.count = count;

  }

}

Java

 

1

2

3

4

5

6

7

public class UpdateErrorEvent {  

  public final String message;

 

  UpdateCompleteEvent(String message){

    this.message = message;

  }

}

组件A:

Java

 

1

2

3

4

5

6

7

8

9

10

EventBus bus = EventBus.getDefault(); // Or better yet, inject it

 

...

 

// when update completes successfully

bus.post(new UpdateCompleteEvent(count));  

...

 

// when there is an error

bus.post(new UpdateErrorEvent(error.getMessage()));

组件B

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

EventBus bus = EventBus.getDefault(); // Or better yet, inject it

 

...

 

public void onEvent(UpdateCompleteEvent event){  

  // TODO - do something with event.count

}  

 

public void onEvent(UpdateErrorEvent event){  

  // TODO - do something with event.message

}  

 

...

 

bus.register(this);

 

...

 

bus.unregister(this);

























  




0 0
原创粉丝点击