EventBus3.0基本使用

一.概述

EventBus是一个用于Android和Java的开源库,使用发布者/订阅者模式实现松散耦合。EventBus使中央通信仅用几行代码就能解耦类——简化代码、消除依赖和加速应用程序开发。 image

二.使用

1.依赖

compile 'org.greenrobot:eventbus:3.0.0'

2.代码中基本使用

(1)首先先定义一个事件,用于事件的发布和消息传递

public class MessageEvent {
    String message;
    public MessageEvent(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

(2)订阅者进行注册和反注册
订阅者进行注册

@Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_home);
        super.onCreate(savedInstanceState);
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }
    }

取消订阅

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

(3)订阅者订阅方法例子: threadMode和priority见方法上的注释

/**
     * ThreadMode.MAIN 事件发送者不论在哪个线程,订阅者都在主线程接收用于刷新ui
     * priority 越大越先收到
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN, priority = 0)
    public void onMessageEvent(MessageEvent event) {
        LogUtil.d(TAG, "onMessageEvent MAIN priority0", event.getMessage(), " thread: ", Thread.currentThread().getName());
    }
    /**
     * ThreadMode.MAIN 事件发送者不论在哪个线程,订阅者都在主线程接收用于刷新ui
     * priority 越大越先收到
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN, priority = 1)
    public void onMessageEvent2(MessageEvent event) {
        LogUtil.d(TAG, "onMessageEvent2 MAIN priority1", event.getMessage(), " thread: ", Thread.currentThread().getName());
    }
    /**
     * ThreadMode.POSTING(默认) 订阅者和事件发送者在同一个线程
     * priority 越大越先收到
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.POSTING, priority = 1)
    public void onMessageEvent3(MessageEvent event) {
        LogUtil.d(TAG, "onMessageEvent3 POSTING", event.getMessage(), " thread: ", Thread.currentThread().getName());
    }
    /**
     * ThreadMode.BACKGROUND
     * 事件发送者在主线程的话,订阅者会在创建的子线程中
     * 事件发送者不在主线程的话,订阅者和事件发送者在同一个线程
     * priority 越大越先收到
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 1)
    public void onMessageEvent4(MessageEvent event) {
        LogUtil.d(TAG, "onMessageEvent4 BACKGROUND", event.getMessage(), " thread: ", Thread.currentThread().getName());
    }
    /**
     * ThreadMode.ASYNC
     * 不论事件发送者在哪一个线程,订阅者都会在重新创建的子线程中
     * priority 越大越先收到
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.ASYNC, priority = 1)
    public void onMessageEvent5(MessageEvent event) {
        LogUtil.d(TAG, "onMessageEvent5 ASYNC", event.getMessage(), " thread: ", Thread.currentThread().getName());
    }

总结一下: EventBus的四种ThreadMode(线程模型)

EventBus3.0有以下四种ThreadMode:

  • POSTING(默认):如果使用事件处理函数指定了线程模型为POSTING,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。
  • MAIN: 事件的处理会在UI线程中执行。事件处理时间不能太长,长了会ANR的。
  • BACKGROUND:如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
  • ASYNC:无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。 (4)事件发布者用法如下: 另起一个activity进行事件发布:
new Thread(new Runnable() {
            @Override
            public void run() {
                EventBus.getDefault().post(new MessageEvent("work thread message"));

            }
        }).start();

        EventBus.getDefault().post(new MessageEvent("main thread test"));

我在子线程和主线程中各发布了一个消息,事件订阅者接收到的log如下:

05-29 13:49:48.050 22933 22933 D HomeActivity: onMessageEvent3 POSTING main thread test  thread:  main 
05-29 13:49:48.050 22933 22933 D HomeActivity: onMessageEvent2 MAIN priority1 main thread test  thread:  main 
05-29 13:49:48.050 22933 22933 D HomeActivity: onMessageEvent MAIN priority0 main thread test  thread:  main 
05-29 13:49:48.050 22933 22982 D HomeActivity: onMessageEvent5 ASYNC main thread test  thread:  pool-1-thread-1 
05-29 13:49:48.051 22933 22981 D HomeActivity: onMessageEvent4 BACKGROUND work thread message  thread:  Thread-209 
05-29 13:49:48.051 22933 22984 D HomeActivity: onMessageEvent5 ASYNC work thread message  thread:  pool-1-thread-3 
05-29 13:49:48.051 22933 22981 D HomeActivity: onMessageEvent3 POSTING work thread message  thread:  Thread-209 
05-29 13:49:48.052 22933 22983 D HomeActivity: onMessageEvent4 BACKGROUND main thread test  thread:  pool-1-thread-2 
05-29 13:49:48.060 22933 22933 D HomeActivity: onMessageEvent2 MAIN priority1 work thread message  thread:  main 
05-29 13:49:48.060 22933 22933 D HomeActivity: onMessageEvent MAIN priority0 work thread message  thread:  main

3.拦截事件的方法源码如下:

public void cancelEventDelivery(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        if (!postingState.isPosting) {
            throw new EventBusException(
                    "This method may only be called from inside event handling methods on the posting thread");
        } else if (event == null) {
            throw new EventBusException("Event may not be null");
        } else if (postingState.event != event) {
            throw new EventBusException("Only the currently handled event may be aborted");
        } else if (postingState.subscription.subscriberMethod.threadMode != ThreadMode.POSTING) {
            throw new EventBusException(" event handlers may only abort the incoming event");
        }

        postingState.canceled = true;
    }

可以看到拦截事件只能在ThreadMode是POSTING的方法上进行拦截

4.粘性事件

除了上面讲的普通事件外,EventBus还支持发送黏性事件,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。
事件发布者发布的事件会保存在内存中,当有订阅者注册已发布的粘性事件时,会直接收到已发布的粘性事件。 在上面例子添加粘性事件代码如下:

发送者先发送粘性事件

EventBus.getDefault().postSticky(new MessageEvent("粘性事件"));

发送者发送粘性事件后,订阅者再去订阅,可以写在onclick()中去订阅:

mStickyBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!EventBus.getDefault().isRegistered(this)) {
                    EventBus.getDefault().register(this);
                }
            }
        });

订阅粘性事件方法如下:

/**
     * 订阅粘性事件
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.POSTING, sticky = true)
    public void onMessageEventSticky(MessageEvent event) {
        LogUtil.d(TAG, "onMessageEventSticky", event.getMessage(), " thread: ", Thread.currentThread().getName());
    }

运行顺序:发布者先发布粘性事件,然后点击按钮订阅者进行注册,然后订阅者收到粘性事件,log如下:

05-29 14:39:39.756 28301 28301 D SystemGarbageActivity: 发布粘性事件 message:  粘性事件
05-29 14:39:44.039 28301 28301 D HomeActivity: 订阅者注册 
05-29 14:39:44.042 28301 28301 D HomeActivity: onMessageEventSticky 粘性事件  thread:  main

三.ProGuard 混淆规则

-keepattributes *Annotation*
-keepclassmembers class * {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
 
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值