EventBus基础介绍

本文介绍了EventBus在Android中的应用,包括EventBus的基本概念、重要角色(Event、Subscriber、Publisher)、四种线程模式(POSTING、MAIN、BACKGROUND、ASYNC)。详细讲解了EventBus的使用方法,包括添加依赖、定义和发布事件、订阅事件,以及粘性事件的使用。此外,还阐述了EventBus事件的优先级及其如何取消事件传递。

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

1. EventBus简介

EventBus是一种用于Android的事件发布-订阅总线,它简化了应用程序内各个组件之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。
EventBus github地址

1.1 三个重要角色

  • Event:事件,它可以是任意类型,EventBus会根据事件类型进行全局的通知。
  • Subscriber:事件订阅者,在EventBus 3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe,并且指定线程模型,默认是POSTING。
  • Publisher:事件的发布者,可以在任意线程里发布事件。一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。

结构图如下:
EventBus结构图

从上图中可以看到这个库整体结构是基于生产者/消费者模式,也可以称呼为发布者/订阅者

1.2四种线程模式

EventBus3.0有四种线程模式,分别如下:

  • POSTING:默认,表示事件处理函数的线程跟发布事件的线程在同一个线程。
  • MAIN:表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
  • BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
  • ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。

2.EventBus的使用

2.1添加依赖

要使用EventBus首先要添加依赖,在build.gradle中dependences里面添加如下:

implementation 'org.greenrobot:eventbus:3.1.1'

2.2基本使用

从EvnetBus的结构图来看,它的实现原理,跟我们日常生活中的微信公众号很类型,首先在使用的时候,我们需要向公众平台注册,注册完之后, 当生产者需要发布信息的时候,平台会帮我们把这些消息推送给订阅者,订阅者根据消息内容,进行不同处理操作。
使用流程如下:
EventBus的使用流程

EventBus基本使用包括三个步骤:定义事件,发布事件, 订阅事件
1.定义事件
事件可以是任意普通的Java对象,没有任何特殊的要求,如下:

 public class MessageEvent {
    private String message;

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    }
  1. 订阅事件
    订阅者需要定义事件处理方法(也称为订阅者方法)。当发布对应类型的事件时,该方法将被调用。EventBus 3使用 @Subscribe 注解来定义订阅者方法。方法名可以是任意合法的方法名,参数类型为订阅事件的类型。如下代码所示:
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
    ...
}

订阅者还需要在总线上注册,并在不需要时在总线上注销。只有订阅者注册了,它们才会收到事件。在Android中,可以根据Activity或者Fragment的生命周期来注册和注销。例如:

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

@Override
protected void onDestroy() {
    super.onDestroy();
    // 注销订阅者
    EventBus.getDefault().unregister(this);
}    
  1. 发布事件。
    在需要的地方发布事件,所有订阅了该类型事件并已注册的订阅者将收到该事件。如下:
// 发布事件
EventBus.getDefault().post(new MessageEvent("Hello EventBus!"));

订阅事件的例子如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    private TextView mTvMessage;

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

    private void initContentView() {
        Button btnStart = findViewById(R.id.btn_main_start_activity);
        mTvMessage = findViewById(R.id.tv_main_message);
        btnStart.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_main_start_activity) {
            SecondActivity.start(this);
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {
        Log.i(TAG, "message is " + event.getMessage());
        // 更新界面
        mTvMessage.setText(event.getMessage());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 注销订阅者
        EventBus.getDefault().unregister(this);
    }
}

MainActivity订阅了MessageEvent事件。当接收到MessageEvent事件时,订阅者方法将打印日志消息,并更新界面上的TextView。

发布事件的例子如下:

public class SecondActivity extends AppCompatActivity implements View.OnClickListener {

    public static void start(Context context) {
        Intent intent = new Intent(context, SecondActivity.class);
        context.startActivity(intent);
    }

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

    private void initContentView() {
        findViewById(R.id.btn_second_post_event).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_second_post_event) {
            // 发布事件
            EventBus.getDefault().post(new MessageEvent("Hello EventBus!"));
        }
    }
}

当点击发布事件的按钮时,SecondActivity将发布一个MessageEvent事件。
运行,点击MainActivity中的启动按钮启动SecondActivity,点击SecondActivity页面的发布事件按钮发布事件,最后回退到MainActivity,可看到界面上的TextView内容更行为“Hello EventBus”

订阅事件的代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";

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

    private void initContentView() {
        findViewById(R.id.btn_main_start_activity).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_main_start_activity) {
            SecondActivity.start(this);
        }
    }

    @Subscribe(threadMode = ThreadMode.POSTING)
    public void onMessageEventPosting(MessageEvent event) {
        Log.i(TAG, "onMessageEventPosting(), current thread is " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEventMain(MessageEvent event) {
        Log.i(TAG, "onMessageEventMain(), current thread is " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    public void onMessageEventMainOrdered(MessageEvent event) {
        Log.i(TAG, "onMessageEventMainOrdered(), current thread is " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onMessageEventBackground(MessageEvent event) {
        Log.i(TAG, "onMessageEventBackground(), current thread is " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void onMessageEventAsync(MessageEvent event) {
        Log.i(TAG, "onMessageEventAsync(), current thread is " + Thread.currentThread().getName());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 注销订阅者
        EventBus.getDefault().unregister(this);
    }
}

MainActivity订阅了MessageEvent事件,定义了5个不同线程模式的订阅者方法。当接收到MessageEvent事件时,订阅者方法将打印当前所在的线程名。

2.3 粘性事件

黏性事件,就是指发送了该事件之后再订阅者依然能够接收到的事件。使用黏性事件的时候有两个地方需要做些修改。一个是订阅事件的地方,这里我们在先打开的Activity中注册监听黏性事件:

@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onGetStickyEvent(MessageWrap message) {
    String txt = "Sticky event: " + message.message;
    getBinding().tvStickyMessage.setText(txt);
}

另一个是发布事件的地方,这里我们在新的开的Activity中发布黏性事件。即调用EventBus的postSticky方法来发布事件

private void publishStickyontent() {
    String msg = getBinding().etMessage.getText().toString();
    EventBus.getDefault().postSticky(MessageWrap.getInstance(msg));
    ToastUtils.makeToast("Published : " + msg);
}

发布一个粘性事件之后,EventBus将一直缓存该粘性事件。如果想要移除粘性事件,那么可以使用如下方法:

// 移除指定的粘性事件
removeStickyEvent(Object event);

// 移除指定类型的粘性事件
removeStickyEvent(Class<T> eventType);

// 移除所有的粘性事件
removeAllStickyEvents();

发布粘性事件示例如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

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

    private void initContentView() {
        findViewById(R.id.btn_main_post_event).setOnClickListener(this);
        findViewById(R.id.btn_main_start_activity).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_main_post_event:
                // 发布粘性事件
                EventBus.getDefault().postSticky(new MessageEvent("Hello EventBus!"));
                break;

            case R.id.btn_main_start_activity:
                SecondActivity.start(this);
                break;

            default:
                break;
        }
    }
}

当点击发布粘性事件的按钮时,MainActivity将发布一个MessageEvent粘性事件。
订阅粘性事件的示例代码如下所示:

public class SecondActivity extends AppCompatActivity {
    private static final String TAG = "SecondActivity";

    private TextView mTvMessage;

    public static void start(Context context) {
        Intent intent = new Intent(context, SecondActivity.class);
        context.startActivity(intent);
    }

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

    private void initContentView() {
        mTvMessage = findViewById(R.id.tv_second_message);
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onMessageEvent(MessageEvent event) {
        Log.i(TAG, "message is " + event.getMessage());
        // 更新界面
        mTvMessage.setText(event.getMessage());
        // 移除粘性事件
        EventBus.getDefault().removeStickyEvent(event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 注销订阅者
        EventBus.getDefault().unregister(this);
    }
}

SecondActivity订阅了MessageEvent粘性事件。当接收到MessageEvent粘性事件时,订阅者方法将打印日志消息,并更新界面上的TextView,最后移除该粘性事件。

3.EventBus事件的优先级

EventBus支持在定义订阅者方法时指定事件传递的优先级。默认情况下,订阅者方法的事件传递优先级为0。数值越大,优先级越高。在相同的线程模式下,更高优先级的订阅者方法将优先接收到事件。注意:优先级只有在相同的线程模式下才有效。

指定事件传递优先级的示例如下所示:

@Subscribe(priority = 1)
public void onMessageEvent(MessageEvent event) {
    ...
}

可以在高优先级的订阅者方法接收到事件之后取消事件的传递。此时,低优先级的订阅者方法将不会接收到该事件。注意: 订阅者方法只有在线程模式为ThreadMode.POSTING时,才可以取消一个事件的传递。

取消事件传递的示例如下所示:

@Subscribe(threadMode = ThreadMode.POSTING, priority = 1)
public void onMessageEvent(MessageEvent event) {
    ...
    // 取消事件传递
    EventBus.getDefault().cancelEventDelivery(event);
}

订阅事件并设置5个优先级的示例如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";

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

    private void initContentView() {
        findViewById(R.id.btn_main_start_activity).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_main_start_activity) {
            SecondActivity.start(this);
        }
    }

    @Subscribe(threadMode = ThreadMode.POSTING, priority = 1)
    public void onMessageEvent1(MessageEvent event) {
        Log.i(TAG, "onMessageEvent1(), message is " + event.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.POSTING, priority = 2)
    public void onMessageEvent2(MessageEvent event) {
        Log.i(TAG, "onMessageEvent2(), message is " + event.getMessage());
        // 取消事件
        EventBus.getDefault().cancelEventDelivery(event);
    }

    @Subscribe(threadMode = ThreadMode.POSTING, priority = 3)
    public void onMessageEvent3(MessageEvent event) {
        Log.i(TAG, "onMessageEvent3(), message is " + event.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.POSTING, priority = 4)
    public void onMessageEvent4(MessageEvent event) {
        Log.i(TAG, "onMessageEvent4(), message is " + event.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.POSTING, priority = 5)
    public void onMessageEvent5(MessageEvent event) {
        Log.i(TAG, "onMessageEvent5(), message is " + event.getMessage());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 注销订阅者
        EventBus.getDefault().unregister(this);
    }
}

在MainActivity中定义了5个优先级,当接收到事件时将会打印方法中输出日志,同时在优先级为2的方法中取消了事件的传递
发布事件的示例代码如下:

public class SecondActivity extends AppCompatActivity implements View.OnClickListener {

    public static void start(Context context) {
        Intent intent = new Intent(context, SecondActivity.class);
        context.startActivity(intent);
    }

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

    private void initContentView() {
        findViewById(R.id.btn_second_post_event).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_second_post_event) {
            // 发布事件
            EventBus.getDefault().post(new MessageEvent("Hello EventBus!"));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值