EventBus3.0——基本使用

来源:互联网 发布:淘宝客服月总结怎么写 编辑:程序博客网 时间:2024/06/05 16:50

EventBus3.0——基本使用

EventBus在线程间通信有着明显的优势,普及度也非常的高,特别是升级到3.0后,使用起来更加方便、简洁,性能也得到了很好优化,并且加入了注解,其使用方式相对以前有了很大的变动,今天我就带大家来学习一下EventBus3.0的基本使用。这里针对的是以前有使用过EventBus的朋友,框架原理就不过多解释了,只贴重要部分源码。基本概念不多说,我这里以fragment之间通信为例,先上效果图:

左边为fragment1、右边为fragment2,使用方法如下:

第一步、注册观察者(订阅者):

1、注册(唯一注册方法)
 @Override    public void onCreate(@Nullable Bundle savedInstanceState) {        EventBus.getDefault().register(this);        super.onCreate(savedInstanceState);    }
2、解除注册
@Override    public void onDestroyView() {        EventBus.getDefault().unregister(this);        super.onDestroyView();    }

注:EventBus.getDefault()的作用是为了获取单例默认实例,register的作用是为了通过反射或者索引方式获取当前类中的注解方法,并存到Map集合中,以便post的时候使用,unregister则是释放Map集合中的缓存。

第二步、创建观察者(订阅者):

一共有四种创建观察者的方法(3.0以前版本,方法名必须如下):
onEvent:发布事件和接收事件在同一线程,不能做耗时操作,容易导致事件分发延迟。onEventMainThread:不论事件在哪个线程中发布,接收事件只在UI线程中执行,也是最常用的订阅函数,不能做耗时操作。onEventBackground:不论事件在哪个线程中发布,接收事件只在子线程中执行,如果事件是在子线程中发布,则接收事件直接在该子线程中执行。onEventAsync:无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync
相信用过EventBus的朋友对这四种观察者方法都非常熟悉,但遗憾了是到了3.0的版本他们就退休了,因为引进了注解@Subscribe,我们通过源码来看一下,这个注解是怎么定义的:
public @interface Subscribe {    ThreadMode threadMode() default ThreadMode.POSTING;    /**     * If true, delivers the most recent sticky event (posted with     * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).     */    boolean sticky() default false;    /** Subscriber priority to influence the order of event delivery.     * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before     * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of     * delivery among subscribers with different {@link ThreadMode}s! */    int priority() default 0;}
一共有三个成员变量:threadMode——线程模式(默认为ThreadMode.POSTING),sticky()——是否具备粘性,priority——优先级,相信这几个变量大家不陌生吧,3.0以前的注册函数传参是不是也有类似的参数,而且有了注解,我们在创建观察者的时候方法名也没有限制了。
那么3.0如何创建观察者呢,3.0版本通过注解描述观察者的信息,更加清晰直观的看到每个方法的线程模式、是否接受粘性消息、优先级,创建方式如下:
 @Subscribe(threadMode = ThreadMode.POSTING,priority = 1)    public void pdmEvent(Student student) {        if (student != null)            tvContent.setText("onEvent " +student.getContent());        Log.e(TAG,"onEvent: " + Thread.currentThread().getName());    }    @Subscribe(threadMode = ThreadMode.MAIN,priority = 2,sticky = true)    public void pdmEventMainThread(Student student) {        if (student != null)            tvContent1.setText( "onEventMainThread " + student.getContent());        Log.e(TAG,"onEventMainThread: " + student.getContent());    }    @Subscribe(threadMode = ThreadMode.BACKGROUND,priority = 3)    public void pdmEventBackground(Student student) {        Log.e(TAG,"onEventBackground: " + Thread.currentThread().getName());    }    @Subscribe(threadMode = ThreadMode.ASYNC,priority = 4)    public void pdmEventAsync(Student student) {        Log.e(TAG,"onEventAsync: " + Thread.currentThread().getName());    }
这里源码是通过获取方法的注解来判断哪些函数是EventBus所需要的观察者方法,通过注解变量threadMode的值判断观察者的线程模式,不再需要根据方法名来判断了。源码用一个枚举来定义ThreadMode,跟原来的四种观察者函数一一对应,这样我们就不需要死死的记着那几个函数名了:
public enum ThreadMode {    POSTING,    MAIN,    BACKGROUND,    ASYNC}

我们来看一下源码是怎么通过注解Subscribe中的属性值来决定观察者执行的线程:

 private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {        switch (subscription.subscriberMethod.threadMode) {//注解Subscribe的ThreadMode属性            case POSTING://当前线程                invokeSubscriber(subscription, event);                break;            case MAIN://主线程                if (isMainThread) {                    invokeSubscriber(subscription, event);                } else {                    mainThreadPoster.enqueue(subscription, event);                }                break;            case BACKGROUND://子线程                if (isMainThread) {                    backgroundPoster.enqueue(subscription, event);                } else {                    invokeSubscriber(subscription, event);                }                break;            case ASYNC://新开子线程                asyncPoster.enqueue(subscription, event);                break;            default:                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);        }    }

第三步、发布事件(fragment2):

@Override    public void onListItemClick(ListView listView, View view, final int position,                                long id) {//        new Thread(new Runnable() {//            @Override//            public void run() {                EventBus.getDefault().post(getListView().getItemAtPosition(position));                Log.e(TAG, "run: " + Thread.currentThread().getName());//            }//        }).start();        super.onListItemClick(listView, view, position, id);    }
到了这里,EventBus的基本使用就讲完,最后我们来验证下threadMode中的四个枚举值的设置,是不是跟以前版本的四种观察者方法能够一一对应,下面看日志打印信息:

明显符合,其他都没有异议,一个萝卜一个坑,但是threadMode = ThreadMode.PSTING是否跟发布事件所在线程一样,对应以前版本的onEvent方法,还有待确定,这里只能看出它在主线程运行,那么我们再将发布事件放到子线程中,来做进一步验证:
@Override    public void onListItemClick(ListView listView, View view, final int position,                                long id) {        new Thread(new Runnable() {            @Override            public void run() {                EventBus.getDefault().post(getListView().getItemAtPosition(position));                Log.e(TAG, "run: " + Thread.currentThread().getName());            }        }).start();        super.onListItemClick(listView, view, position, id);    }
默认模式的观察者也要记得修改,因为它所在线程跟发布事件线程是一样的,记得注释掉UI操作部分:
 @Subscribe(threadMode = ThreadMode.POSTING,priority = 1)    public void pdmEvent(Student student) {//        if (student != null)//            tvContent.setText("onEvent " +student.getContent());        Log.e(TAG,"onEvent: " + Thread.currentThread().getName());    }
再看打印日志:

发布事件的当前线程是Thread-146,threadMode = ThreadMode.PSTING所在方法线程也是Thread-146,到了这里最后一点疑虑也解决了,ThreadMode四个枚举值分别对应了以前版本的四种观察者方法
下一章我会就EventBus注解(@Subscribe)中stick和priority的使用做讲解。(有时间也会专门针对3.0的源码做一下阐述)
最后给没用过EventBus的朋友提供一个小demo参考:http://download.csdn.net/detail/aiyh0202/9662495



1 0