android开发中EventBus事件发布-订阅总线使用详解

一、简介
1、EventBus是一种用于Android的事件发布-订阅总线,它简化了应用程序内各个组件之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。

2、事件可以是任意类型,EventBus会根据事件类型进行全局的通知,在EventBus 3.0之前接收事件必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe,并且指定线程模型,默认是POSTING

3、四种线程模型:
POSTING:默认,表示事件处理函数的线程跟发布事件的线程在同一个线程。

MAIN:表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。

BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程

ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作

二、EventBus的使用(包含粘性事件)

1、在build.gradle中添加依赖

implementation 'org.greenrobot:eventbus:3.1.1' //eventbus事件

2、在需要接收事件的类中,初始化中定义,销毁时一并销毁,这里已service为例
在启动service的onStartCommand类中注册时:

`@Override
public int onStartCommand(Intent intent, int flags, int startId) 
{    
EventBus.getDefault().register(this);    
return super.onStartCommand(intent, flags, startId);
}`

3、定义接收事件的方法
注:在接收和发送事件时我定义了事件类和事件类型的一个类,在后面会贴出代码
也会给记录不定义任何类的发送和接收
同时记录下自己在activity中发送事件在service中接收时的bug

不定义事件类时的接收

 @Subscribe(threadMode = ThreadMode.MAIN)//处理一般事件    
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)//处理粘性事件    
public void receiveStatus(String event) {       {        

​         }    }

定义事件类时的接收:

`//@Subscribe(threadMode = ThreadMode.MAIN)//处理一般事件    
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)//处理粘性事件    
public void receiveStatus(JPushEvent event) {        
if(EventType.SUCCESS_PERMISSIONS.equals(event.getType())){
//开始定位            
//hasPermission = true;        
}    
}`

注:这里使用了粘性事件,因为这里的事件在启动该service的acvitivy中发布,不能保证发布事件时该订阅者已经注册
粘性事件稍后会详细讲

4、发送事件
在任何需要发送事件的地方进行发送,这里已调用该service的Activity为例,同样
也记录不定义事件类和定义事件类的发送:

不定义时发送:

EventBus.getDefault().post("发送的数据"));

定义事件类时:
在该activity的onCreate方法中:

`@Override    
protected void onCreate(Bundle savedInstanceState) {        
super.onCreate(savedInstanceState);        
setContentView(R.layout.activity_main);        
Intent intent = new Intent(MainActivity.this, LocationService.class);        
startService(intent);        `
`EventBus.getDefault().postSticky(new JPushEvent(new Object(), EventType.SUCCESS_PERMISSIONS));//发送粘性事件//      
`EventBus.getDefault().post(new JPushEvent(new Object(), EventType.SUCCESS_PERMISSIONS));//发送一般事件    }`

在这里,我一开始就是以为先启动了service再发送事件在service中肯定能接收到,但是其实启动service和发送事件并不在同一个线程中,所以并不能保证事件发送之前在service中已经注册了订阅者
所以用粘性事件,发送一般事件也写了

5、注销事件:
为例不使内存泄漏导致最终内存溢出。在注册事件的service中的onDestroy()方法中来注销事件,
粘性事件和一般事件的注册方法一致,注销方法稍微不一致,


    @Overridepublic void onDestroy() {    super.onDestroy();    
    EventBus.getDefault().unregister(this);//注销一般事件    
    EventBus.getDefault().removeAllStickyEvents();//注销粘性事件
    }
    ```

在这个例子中使用的事件类:

    public class JPushEvent {    
    private Object message;    
    private String type;    
    public JPushEvent(Object message,String type) {       
    this.message = message;        
    this.type = type;    
    }    
    public Object getMessage() {        
    return message;    
    }    
    public void setMessage(Object message) {        
    this.message = message;    
    }    
    public String getType() {        
    return type;   
     }    
     public void setType(String type) {       
      this.type = type;    
      }}

//同时为类型也定义了一个类在下方代码块中:(可以不使用)

/** * 事件类型定义 */
public class EventType {    
public static final String JPUSH_EVENT = "JPUSH_EVENT";//极光推送接收事件    
public static final String LOCATION_EVENT = "LOCATION_EVENT";//获取位置信息事件    
public static final String SUCCESS_PERMISSIONS ="SUCCESS_PERMISSIONS";//获取权限成功事件}
```

三、粘性事件和优先级

所谓的黏性事件,就是指发送了该事件之后再订阅者依然能够接收到的事件,就像我遇到的问题一样

粘性事件和一般事件有两点不同:
1、事件的订阅:

`@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)`

2、事件的注销:

`EventBus.getDefault().removeAllStickyEvents();`

优先级:


    @Subscribe(threadMode = ThreadMode.POSTING, sticky = true, priority = 1)

优先级越高越先接收到事件

发布了43 篇原创文章 · 获赞 22 · 访问量 5953

猜你喜欢

转载自blog.csdn.net/qq_41466437/article/details/100677314