EventBus使用及解析

作者: 奔跑吧李博 | 来源:发表于2018-10-16 00:18 被阅读112次

    在我们刚学Android不久,就会学到用接口回调来异步通知事件。写起来也算顺手,但是接口回调需要不断地设置listener,耦合性较大,当项目越来越复杂,接口回调的传值会形成一张错综复杂的网,有这样使用经历的人就会深有感触。于是,就可以使用EventBus的事件传递方法,在发送着和接收者完全解耦,传递接收范围广,接下来就学习怎样使用Eventbus。

    事件产生过程

    流程示意图

    EventBus的三要素

    Event:事件,可以是任意类型的对象。
    Subscriber:事件订阅者,在EventBus3.0之前消息处理的方法只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,他们分别代表四种线程模型。而在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为POSTING)。
    Publisher:事件发布者,可以在任意线程任意位置发送事件,直接调用EventBus的post(Object)方法。可以自己实例化EventBus对象,但一般使用EventBus.getDefault()就好了,根据post函数参数的类型,会自动调用订阅相应类型事件的函数。

    使用步骤

    引入库

        implementation 'org.greenrobot:eventbus:3.0.0'
    

    这里可以看到EventBus.getDefault()内部调用的是懒汉式的单例获取Eventbus对象方法。

        /** Convenience singleton for apps using a process-wide EventBus instance. */
        public static EventBus getDefault() {
            if (defaultInstance == null) {
                synchronized (EventBus.class) {
                    if (defaultInstance == null) {
                        defaultInstance = new EventBus();
                    }
                }
            }
            return defaultInstance;
        }
    

    创建发送的实体类,根据发送者的实体类和接收者的实体类相匹配来看是否接收事件。

    public class PostMsg {
        private int num;
        private String title;
    
        public PostMsg(int num, String title) {
            this.num = num;
            this.title = title;
        }
    
        public int getNum() {
            return num;
        }
    
        public void setNum(int num) {
            this.num = num;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    }
    

    在任意需要发送事件的地方发送消息,对,发送就是这么简单:

    EventBus.getDefault().post(new PostMsg(100,"这里是标题"));
    

    接收消息的地方需要在onCreate()方法中进行注册

            EventBus.getDefault().post(this);
    

    在onDestroy()方法中取消注册(避免内存泄漏)

        @Override
        protected void onDestroy() {
            super.onDestroy();
            EventBus.getDefault().unregister(this);
        }
    

    接收消息

        @Subscribe(threadMode = ThreadMode.MAIN)
        public void onEventMainThread(PostMsg postMsg){
            Toast.makeText(getApplicationContext(),postMsg.getNum() + "  " + postMsg.getTitle(),Toast.LENGTH_LONG).show();
        }
    

    线程模式

    public enum ThreadMode {
    
        POSTING,
    
        MAIN,
    
        BACKGROUND,
    
        ASYNC
    }
    

    POSTING:订阅者方法将在发布事件所在的线程中被调用。是默认的线程模式,该模式不会切换线程,意味着最少的性能开销。可能会发生下主线程。
    MAIN:订阅者方法将在主线程中被调用。
    BACKGROUND:订阅者方法将在后台线程中被调用。如果发布事件的线程不是主线程,那么订阅者方法将直接在该线程中被调用。如果发布事件的线程是主线程,那么将使用一个单独的后台线程
    ASYNC:订阅者方法将在一个单独的线程中被调用,该模式可用来执行耗时操作。

    粘性事件

    当有需求需要发送消息,所有注册过的Activity都能收到。但是此时只有一部分Activity创建了,那么此时发出消息,未创建的Activity就接收不到消息。粘性事件就解决了该问题。通过 postSticky 发送粘性事件,这个事件不会只被消费一次就消失,而是一直存在系统中,直到被 removeStickyEvent 删除掉。

    发布粘性事件

    EventBus.getDefault().postSticky(new PostMsg(100,"这里是标题"));
    

    接收粘性事件

        @Subscribe(sticky = true)
        public void onEventMainThread(PostMsg postMsg){
    
        }
    

    移除指定粘性事件

            //移除某种类型粘性事件
            EventBus.getDefault().removeStickyEvent(ThreadMode.xxx);
            //移除某种对象粘性事件
            EventBus.getDefault().removeStickyEvent(object);
             //移除所有粘性事件
            EventBus.getDefault().removeAllStickyEvents();
    

    相关文章

      网友评论

      • 15ecf25f298a:eventbus我也一直在用
        奔跑吧李博:@持续进化的程序猿 用当然没问题,用多了也会把页面关系弄复杂

      本文标题:EventBus使用及解析

      本文链接:https://www.haomeiwen.com/subject/wzcnwxtx.html