一、EventBus机制简介
EventBus支持单例模式,也支持建造者模式用于定制处理。,可以定制处理线程池,异常抛出开关,log记录开关等。
主要是为了解决不同线程处理之后得到的数据的在其他线程(一般是主线程)的处理问题。
使用方式
注册EventBus.getDefault().register(Object );
反注册:EventBus.getDefault.unregister(Object );
抛出数据:EventBus.getDefault.post(Object);
在注册的对象对应的类中使用@Subscribe注解标记处理函数。
1、’只能在安卓中使用,因为使用了Looper来查找主线程,Looper是android.os包中的类
2、同一个类的不同实例注册,使用的都是类本身的所有方法,并不会多次记录这个类的信息。
3、Register
会对注册的实例从其对应的类开始,查找父类,如果父类的全包路径是以“java”、“javax”、“android”开头,就不会查找其父类
对于注册的实例,会查找对应类和父类的所有标记的处理函数。
4、Post
对于Post出来的数据类型,也会查找其所有的父类型以及其每一个父类中包含的接口以及接口的父类型
Post出来的数据类型格式(List):父类型,父类型实现接口1,父类型实现接口1的父接口1.。。。一直查找其父类型的父类型以及其对应实现接口和接口的父接口。所以这里用到了递归查找。
5、处理函数ThreadMode类型,在EventBus.postToSubscription()中有说明
POSTING:在调用EventBus函数的地方直接处理,不管是不是主线程。
MAIN:等待主线程处理,如果当前线程是主线程,使用Handler排队处理,如果不是主线程,排入处理队列;从这里可以发现,其实eventbus的处理性能并不会比平时的处理方式高,相反,由于需要判断存储数据类型,反而会微微降低。
BACKGROUND:使用当前子线程或者EventBus的内部线程池开启专用线程管理处理。如果当前线程是主线程,就将事件插入到EventBus内部线程池中排队等待处理,如果不是主线程,直接在当前子线程处理。
ASYNC:只能使用EventBus内部的线程池开启专用线程处理。当有数据抛出,直接放到子线程中处理。这个专用线程和BACKGROUND中的专用线程使两个Runnable。
二、好处
其好处并不在于处理性能的增加,而是使用的方便,以及处理时机和场景多样化(分配到不同线程中处理)
三、问题
EventBus的使用要注意两个问题:
l 注册与反注册时间点的把握
l 传入实参的类型必须要加以区分。
问题场景:
viewpager中包含fragment A和fragment B。A和B中都开启了单独的线程需要抛出数据让其对应的处理函数处理func_a,func_b,A和B中的EventBus的注册和反注册分别放在onResume和onPause中。但是由于A抛出的数据是ArrayList,B中抛出的数据是ArrayList。此时A抛出的数据会被func_a和func_b处理,B抛出的数据也会被func_a和func_b处理。
处理方法:
方法一:出现这种问题是因为EventBus不会识别类中的使用的泛型,只是识别类本身和其父类,如果有一样的父类(Object除外),都会传入处理,因此可以在处理函数中对于获得数据的类型和其泛型实例做进一步的判断,然后再处理。
方法二:每一种抛出的数据都定义一个专门的类进行包裹,然后再抛出处理。
方法三:在viewpager的PageChangeListener中进行EventBus的注册于反注册,更加精细的控制处理函数的生命周期。