Android EventBus 3.0.0 使用总结(必看篇)

发布时间 - 2026-01-11 01:08:53    点击率:

前言

EventBus框架

EventBus是一个通用的叫法,例如Google出品的Guava,Guava是一个庞大的库,EventBus只是它附带的一个小功能,因此实际项目中使用并不多。用的最多的是greenrobot/EventBus,这个库的优点是接口简洁,集成方便,但是限定了方法名,不支持注解。另一个库square/otto修改自 Guava ,用的人也不少。所以今天我们研究的目标是greenrobot的EventBus.

EventBus 简介

1、EventBus3.0.0 是最新的版本。
2、EventBus 是Android 发布/订阅事件总线,可简化 Activities, Fragments, Threads, Services 等组件间的消息传递。
3、可替代 Intent, Handler, BroadCast ,接口等传统方案,更快,代码更小,50K 左右的 jar 包,代码更优雅,彻底解耦。

github地址:https://github.com/greenrobot/EventBus

EventBus原理图

如何添加依赖

在module的build.gredle 文件中的dependencies标签中添加

compile 'org.greenrobot:eventbus:3.0.0'

例如

apply plugin: 'com.android.application'

android {
  compileSdkVersion 24
  buildToolsVersion "24.0.3"

  defaultConfig {
    applicationId "com.eventbus.app"
    minSdkVersion 14
    targetSdkVersion 24
    versionCode 1
    versionName "1.0"

  }
  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  compile 'com.android.support:appcompat-v7:24.2.1'

  compile 'org.greenrobot:eventbus:3.0.0'
}

如何使用

注册事件

EventBus.getDefault().register( this );

取消注册

EventBus.getDefault().unregister( this );

发送数据

EventBus.getDefault().post( "我发射了");

简单小例子:使用EventBus传递简单字符串

package com.eventbus.app;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //注册
    EventBus.getDefault().register( this );


    findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        EventBus.getDefault().post( "我发射了");
      }
    });
  }

  /**
   * 自定义一个方法 hello() ,用来接收事件。
   * 方法名字可以随便写
   * @return
   */

  @Subscribe(threadMode = ThreadMode.MAIN)
  public void hello ( String event){
    /* Do something */
    Toast.makeText( this , event , Toast.LENGTH_SHORT).show();
  };


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

    //取消注册 , 防止Activity内存泄漏
    EventBus.getDefault().unregister( this );
  }
}

线程模型

在接收事件消息的方法中,可以通过注解的方式设置线程模型,EventBus内置了4中线程模型,分别是ThreadMode.POSTING 、ThreadMode.MAIN、ThreadMode.BACKGROUND、ThreadMode.ASYNC

比如:

@Subscribe(threadMode = ThreadMode.POSTING)
  public void onMessageEventPostThread(String event) {
    Log.e( "event PostThread", "消息: " + event + " thread: " + Thread.currentThread().getName() );
  }

  @Subscribe(threadMode = ThreadMode.MAIN)
  public void onMessageEventMainThread(String event) {
    Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }

  @Subscribe(threadMode = ThreadMode.BACKGROUND)
  public void onMessageEventBackgroundThread(String event) {
    Log.e( "event BackgroundThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }

  @Subscribe(threadMode = ThreadMode.ASYNC)
  public void onMessageEventAsync(String event) {
    Log.e( "event Async", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }

PostThread:如果使用事件处理函数指定了线程模型为PostThread,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为PostThread的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。

MainThread:如果使用事件处理函数指定了线程模型为MainThread,那么不论事件是在哪个线程中发布出来的,该事件处理函数都会在UI线程中执行。该方法可以用来更新UI,但是不能处理耗时操作。

BackgroundThread:如果使用事件处理函数指定了线程模型为BackgroundThread,那么如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。

Async:如果使用事件处理函数指定了线程模型为Async,那么无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。同样,此事件处理函数中禁止进行UI更新操作。

小例子1: 在子线程发送数据

package com.eventbus.app;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //注册
    EventBus.getDefault().register( this );

    findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        new Thread(new Runnable() {
          @Override
          public void run() {
            Log.d( "event 发射数据线程 : " , Thread.currentThread().getName() ) ;
            EventBus.getDefault().post( "我发射了");
          }
        }).start() ;
      }
    });
  }


  @Subscribe(threadMode = ThreadMode.POSTING)
  public void onMessageEventPostThread(String event) {
    Log.e( "event PostThread", "消息: " + event + " thread: " + Thread.currentThread().getName() );
  }

  @Subscribe(threadMode = ThreadMode.MAIN)
  public void onMessageEventMainThread(String event) {
    Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }

  @Subscribe(threadMode = ThreadMode.BACKGROUND)
  public void onMessageEventBackgroundThread(String event) {
    Log.e( "event BackgroundThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }

  @Subscribe(threadMode = ThreadMode.ASYNC)
  public void onMessageEventAsync(String event) {
    Log.e( "event Async", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }


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

    //取消注册 , 防止Activity内存泄漏
    EventBus.getDefault().unregister( this );
  }
}

运行结果:

D/event 发射数据线程 :: Thread-109
E/event BackgroundThread: 消息: 我发射了 thread: Thread-109
E/event PostThread: 消息: 我发射了 thread: Thread-109
E/event Async: 消息: 我发射了 thread: pool-1-thread-2
E/event MainThread: 消息: 我发射了 thread: main

小例子2: 在主线程发送数据

package com.eventbus.app;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //注册
    EventBus.getDefault().register( this );

    findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Log.d( "event 发射数据线程 : " , Thread.currentThread().getName() ) ;
        EventBus.getDefault().post( "我发射了");
      }
    });
  }

  @Subscribe(threadMode = ThreadMode.POSTING)
  public void onMessageEventPostThread(String event) {
    Log.e( "event PostThread", "消息: " + event + " thread: " + Thread.currentThread().getName() );
  }

  @Subscribe(threadMode = ThreadMode.MAIN)
  public void onMessageEventMainThread(String event) {
    Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }

  @Subscribe(threadMode = ThreadMode.BACKGROUND)
  public void onMessageEventBackgroundThread(String event) {
    Log.e( "event BackgroundThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }

  @Subscribe(threadMode = ThreadMode.ASYNC)
  public void onMessageEventAsync(String event) {
    Log.e( "event Async", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }


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

    //取消注册 , 防止Activity内存泄漏
    EventBus.getDefault().unregister( this );
  }
}

运行结果:

D/event 发射数据线程 :: main
E/event MainThread: 消息: 我发射了 thread: main
E/event PostThread: 消息: 我发射了 thread: main
E/event Async: 消息: 我发射了 thread: pool-1-thread-3
E/event BackgroundThread: 消息: 我发射了 thread: pool-1-thread-4

黏*件

除了上面讲的普通事件外,EventBus还支持发送黏*件。何为黏*件呢?简单讲,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。具体用法如下:

注册

EventBus.getDefault().register( this );

事件接收

@Subscribe(threadMode = ThreadMode.MAIN , sticky = true )
public void onMessageEventMainThread(String event) {
Log.e( "event MainThread", "消息: " + event + " thread: " + > Thread.currentThread().getName());
}

取消注册

EventBus.getDefault().unregister( this ) ;

发送事件

EventBus.getDefault().postSticky( "我发射了");

小例子:在MainActivity发送事件,在Activity2里注册并且接收事件

MainActivity源码

package com.eventbus.app;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import org.greenrobot.eventbus.EventBus;

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Log.d( "event 发射数据线程 : " , Thread.currentThread().getName() ) ;
        EventBus.getDefault().postSticky( "我发射了");

        startActivity( new Intent( MainActivity.this , Activity2.class ));
      }
    });
  }
}

Activity2源码

package com.eventbus.app;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class Activity2 extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_2);
    //注册
    EventBus.getDefault().register( this );
  }

  @Subscribe(threadMode = ThreadMode.MAIN , sticky = true )
  public void onMessageEventMainThread(String event) {
    Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    //取消注册 , 防止Activity内存泄漏
    EventBus.getDefault().unregister( this ) ;
  }
}

这就是粘*件,能够收到订阅之前发送的消息。但是它只能收到最新的一次消息,比如说在未订阅之前已经发送了多条黏性消息了,然后再订阅只能收到最近的一条消息。

EventBus源码分析

Subscribe 接口源码

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
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.POSTING ;默认黏*件为false,也就是默认不开启黏*件;默认的优选级为0 。

EventBus 类部分源码

static volatile EventBus defaultInstance;
 
  /** 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;
  }

getDefault() 是一个单例模式 , 只有一个实例对象。

ThreadMode 类源码

public enum ThreadMode {

  /**
   * Subscriber will be called in the same thread, which is posting the event. This is the default. Event delivery
   * implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for
   * simple tasks that are known to complete is a very short time without requiring the main thread. Event handlers
   * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
   */
   
  POSTING,

  /**
   * Subscriber will be called in Android's main thread (sometimes referred to as UI thread). If the posting thread is
   * the main thread, event handler methods will be called directly. Event handlers using this mode must return
   * quickly to avoid blocking the main thread.
   */
   
  MAIN,

  /**
   * Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods
   * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
   * background thread, that will deliver all its events sequentially. Event handlers using this mode should try to
   * return quickly to avoid blocking the background thread.
   */
   
  BACKGROUND,

  /**
   * Event handler methods are called in a separate thread. This is always independent from the posting thread and the
   * main thread. Posting events never wait for event handler methods using this mode. Event handler methods should
   * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
   * of long running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus
   * uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications.
   */

  ASYNC
}

这个类是枚举类,定义了线程模型中的几种类型。

以上这篇Android EventBus 3.0.0 使用总结(必看篇)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


# android  # eventbus  # 3.0  # Android实现EventBus登录界面与传值(粘性事件)  # Android 消息分发使用EventBus的实例详解  # Android中使用开源框架eventbus3.0实现fragment之间的通信交互  # Android之利用EventBus发送消息传递示例  # Android 中 EventBus 的使用之多线程事件处理  # Android EventBus(普通事件/粘性事件)详解  # 射了  # 是一个  # 会在  # 是在  # 给大家  # 的人  # 就会  # 在这个  # 在此  # 这就是  # 也能  # 可以通过  # 希望能  # 然后再  # 自定义  # 只有一个  # 更快  # 不支持  # 可以看出  # 这篇 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?  Laravel如何与Inertia.js和Vue/React构建现代单页应用  Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives  ,网页ppt怎么弄成自己的ppt?  宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程  网站制作壁纸教程视频,电脑壁纸网站?  Python高阶函数应用_函数作为参数说明【指导】  Android 常见的图片加载框架详细介绍  Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理  Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)  微信小程序 canvas开发实例及注意事项  Laravel怎么实现支付功能_Laravel集成支付宝微信支付  如何在云服务器上快速搭建个人网站?  东莞专业网站制作公司有哪些,东莞招聘网站哪个好?  php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】  java获取注册ip实例  如何快速配置高效服务器建站软件?  Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】  Laravel如何升级到最新版本?(升级指南和步骤)  Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程  清除minerd进程的简单方法  Laravel队列由Redis驱动怎么配置_Laravel Redis队列使用教程  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  智能起名网站制作软件有哪些,制作logo的软件?  EditPlus中的正则表达式实战(5)  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  C++用Dijkstra(迪杰斯特拉)算法求最短路径  Bootstrap CSS布局之列表  Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】  简历在线制作网站免费版,如何创建个人简历?  企业网站制作这些问题要关注  如何为不同团队 ID 动态生成多个独立按钮  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】  Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程  如何在建站之星网店版论坛获取技术支持?  悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】  Laravel表单请求验证类怎么用_Laravel Form Request分离验证逻辑教程  Laravel如何正确地在控制器和模型之间分配逻辑_Laravel代码职责分离与架构建议  如何在建站宝盒中设置产品搜索功能?  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  Laravel如何使用Collections进行数据处理?(实用方法示例)  Laravel如何为API编写文档_Laravel API文档生成与维护方法  Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康  Laravel如何处理和验证JSON类型的数据库字段  Laravel如何设置自定义的日志文件名_Laravel根据日期或用户ID生成动态日志【技巧】  iOS中将个别页面强制横屏其他页面竖屏  详解jQuery中的事件  如何在VPS电脑上快速搭建网站?