EventBus3的使用实战(一)

本文详细介绍EventBus3的基本使用方法及与EventBus2的区别,包括事件发布、处理及线程模式选择等内容,并通过实例演示如何正确配置和使用EventBus3。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

EventBus3的使用实战(一)

eventbus2学习参考:http://blog.youkuaiyun.com/lmj623565791/article/details/40794879

eventbus3与eventbus2的区别:

eventbus2,在接收事件的方法名上使用约定的命名,通过方法的名字判定是否是接收事件的方法,以及在哪个线程处理事件,因此使用eventbus2时,要注意接收事件方法的命名,eventbus3使用,接收方法命名可以随意起来,但是方法内参数要和发送事件的参数类型对应,通过注解来取代eventbus2的约定命名,这是eventbus2和eventbus3使用的主要区别,eventbus3中也添加了一些新的方法;

阅读本文需要对EventBus3有一定的了解,如不了解,可以先阅读这篇博客:http://blog.youkuaiyun.com/songdongwan/article/details/64244411

通过一个简单的例子来对EventBus3使用练习一下;

项目布局很简单,只是两个按钮,布局代码不帖出来了,通过两个按钮分别从UI线程和子线程post事件

这里写图片描述

post事件代码:

//从子线程post事件
mThreadBtn.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
           new Thread() {
               @Override
               public void run() {
                   EventBus.getDefault().post(new MyEvent());
                   Log.e("thread", "runnable" + Thread.currentThread());
               }
           }.start();
       }
   });



--------------------------------------------------

//从主线程post事件

mMainBtn.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View view) {
              EventBus.getDefault().post(new MyEvent());
          }
      });


注册和解除注册

@Override
   protected void onStart() {
       super.onStart();
       EventBus.getDefault().register(this);
   }


   @Override
   protected void onStop() {
       super.onStop();

       EventBus.getDefault().unregister(this);
   }

事件处理代码:

@Subscribe(threadMode = ThreadMode.MAIN, priority = 1)
   public void onHandleEvent1(MyEvent myEvent) {
       myEvent.makeToast("sdongwan", this);

       Log.e("thread", "onHandleEvent1: " + Thread.currentThread());

   }

   @Subscribe(threadMode = ThreadMode.MAIN)
   public void onHandleEvent2(MyEvent myEvent) {

       myEvent.makeToast("bcy", this);
       Log.e("thread", "onHandleEvent2: " + Thread.currentThread());

   }

   @Subscribe(threadMode = ThreadMode.POSTING, priority = 2)
   public void onHandleEvent3(MyEvent myEvent) {
       //myEvent.makeToast("posting", this);
       Log.e("thread", "onHandleEvent3: " + Thread.currentThread());
   }


   @Subscribe(threadMode = ThreadMode.BACKGROUND)
   public void onHandleEvent4(MyEvent myEvent) {
       Log.e("thread", "onHandleEvent4: " + Thread.currentThread());

   }

   @Subscribe(threadMode = ThreadMode.BACKGROUND)
   public void onHandleEvent5(MyEvent myEvent) {
       Log.e("thread", "onHandleEvent5: " + Thread.currentThread());

   }

   @Subscribe(threadMode = ThreadMode.ASYNC)
   public void onHandleEvent6(MyEvent myEvent) {
       Log.e("thread", "onHandleEvent6: " + Thread.currentThread());

   }


   @Subscribe(threadMode = ThreadMode.ASYNC)
   public void onHandleEvent7(MyEvent myEvent) {
       Log.e("thread", "onHandleEvent7: " + Thread.currentThread());

   }

  • 点击一次子线程按钮,从子线程post事件,打印的log如下:
    这里写图片描述

onHandleEvent3,onHandleEvent4,onHandleEvent5都在子线程中处理事件,并且在post事件的子线程中;

onHandleEvent6,onHandleEvent7在同一个线程池中的不同子线程处理事件;

onHandleEvent1,onHandleEvent2在主线程中,并且onHandleEvent1先被调用;

  • 点击一次main线程按钮,从UI线程中post事件,打印的log如下:
    这里写图片描述

onHandleEvent1,onHandleEvent2,onHandleEvent3都在主线程中;

onHandleEvent4,onHandleEvent5在同一个线程池的相同线程中;

onHandleEvent6,onHandleEvent7在同一个线程池的不同线程中;

从上面可以得出:

  • priority 优先级越大,越先回调事件处理方法,这个例子中onHandleEvent3优先级最大为2,其次onHandleEvent1的优先级为1,其他事件处理方法优先级默认为0,但从上面的图片中看到事件回调的顺序不是onHandleEvent3,接着onHandleEvent1,因为优先级只用于同一个mode来调整顺序,不同mode顺序无法根据优先级比较;

  • threadmode=ThreadMode.MAIN 在main线程中回调事件处理方法;

  • threadMode = ThreadMode.POSTING 如果post事件的线程是main线程,则在main线程中回调事件处理方法;如果post事件的线程是子线程,则在post事件的线程中回调事件处理方法,简而言之,就是在post事件的线程中回调事件处理方法;

  • threadMode = ThreadMode.BACKGROUND 如果post事件的线程是main线程,则在线程池中找出一条线程,用来当作background线程,其他的ThreadMode.BACKGROUND事件处理方法全部在这个background线程中回调;如果post事件的线程是子线程,则在post事件的线程中回调事件处理方法,总之,background线程肯定是子线程,且只有一个background线程;

  • threadMode = ThreadMode.ASYNC 不管post事件的线程是main线程还是子线程,这个mode下的事件处理方法回调在单独的子线程中,每个事件处理方法独享一个子线程,由于eventbus底层用线程池,所以也就是同一个线程池的不同线程;

配置EventBus3

在MyApplication中配置EventBus3

public class MyApplication extends Application {

    public static EventBus eventBus;
    @Override
    public void onCreate() {
        super.onCreate();

          //1
         EventBus.builder().throwSubscriberException(false).installDefaultEventBus();// 捕获异常,程序不会奔溃;


         //2
                //EventBus.builder().throwSubscriberException(true).installDefaultEventBus();//未捕获异常,程序奔溃;


         //3
//        EventBus.builder()
//                .logNoSubscriberMessages(true)
//                .sendNoSubscriberEvent(true)
//                .installDefaultEventBus();

          //4
//        EventBus.builder()
//                .logNoSubscriberMessages(false)
//                .sendNoSubscriberEvent(false)
//                .installDefaultEventBus();
    }
}
  • 在My Application中配置 1 代码,代码的意义是:当事件处理方法中抛出异常时,由eventbus捕获异常,处理异常,app不会奔溃;可以自己写个订阅者来处理异常,方法参数类型为SubscriberExceptionEvent
@Subscribe
    public void onCatchError(SubscriberExceptionEvent subscriberExceptionEvent){

        Log.e("thread", "onCatchError: "+subscriberExceptionEvent.toString() );

    }
  • 在My Application中配置 2 代码,代码意义是:不捕获异常信息,直接抛出异常,app奔溃,此时自己无法处理异常;

  • 在My Application中配置 3 代码,一开始我没有看懂这是什么意思,有什么作用,查看源码后,才发现它的作用;源码如下:

//EventBus.java源码中postSingleEvent方法片段
if (logNoSubscriberMessages) {
           Log.d(TAG, "No subscribers registered for event " + eventClass);
       }
       if (logNoSubscriberMessages && eventClass != NoSubscriberEvent.class &&
               eventClass != SubscriberExceptionEvent.class) {
           post(new NoSubscriberEvent(this, event));
       }

我们在builder中设置logNoSubscriberMessages(false)和sendNoSubscriberEvent(false)只是设置对应的变量bool值,当logNoSubscriberMessages为true,会打印一段日志,当logNoSubscriberMessages为true,以及事件类型不是event.class和SubscriberExceptionEvent.class时,就会post一个事件,参数类型为NoSubscriberEvent;

我们新添加一个订阅者,用来处理NoSubscriberEvent事件:

@Subscribe
  public void onHandleEvent7(NoSubscriberEvent n) {
      Log.e("thread", "onHandleEvent7: " + Thread.currentThread() +n.toString());

  }

事件处理中打印出一段日志,当我们把匹配post事件类型(MyEvent)的订阅者注释掉后,重新post事件,运行结果如下:
这里写图片描述

可以发现,打印出一段日志,以及我们自己的事件处理,可以通过这个方法来对没有匹配类型的事件进行处理;

  • 在My Application中配置 4 代码,不会打印日志,不会回调NoSubscriberEvent事件处理;

注意:当我们post出一个类型事件,没有相应类型的订阅者来处理,eventbus3中会app奔溃,报错:

MainActivity and its super classes have no public methods with the @Subscribe annotation

EventBus3默认会post出NoSubscriberEvent事件,只要我们书写了NoSubscriberEvent类型的订阅者,自己处理事件后,程序就不会奔溃;

下一篇将介绍EventBus sticky event的使用,以及其他的方面;

EventBus3使用实战(二)

如有不对的地方,欢迎大家留言指出。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值