【Android】使用EventBus进行线程间通讯

EventBus

简介

EventBus:github

EventBus是Android和Java的发布/订阅事件总线。

  • 简化组件之间的通信
    • 解耦事件发送者和接收者

    • 在 Activities, Fragments, background threads中表现良好

    • 避免复杂且容易出错的依赖关系和生命周期问题

Publisher使用post发出一个Event事件,Subscriber在onEvent()函数中接收事件。
EventBus 是一款在 Android 开发中使用的发布/订阅事件总线框架,基于观察者模式,将事件的接收者和发送者分开,简化了组件之间的通信,使用简单、效率高、体积小!下边是官方的 EventBus 原理图:

导入

Android Projects:

implementation("org.greenrobot:eventbus:3.2.0")

Java Projects:

implementation("org.greenrobot:eventbus-java:3.2.0")
<dependency>
    <groupId>org.greenrobot</groupId>
    <artifactId>eventbus-java</artifactId>
    <version>3.2.0</version>
</dependency>

配置

配置混淆文件

-keepattributes *Annotation*
-keepclassmembers class * {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# If using AsyncExecutord, keep required constructor of default event used.
# Adjust the class name if a custom failure event type is used.
-keepclassmembers class org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

# Accessed via reflection, avoid renaming or removal
-keep class org.greenrobot.eventbus.android.AndroidComponentsImpl

使用

简单流程

  1. 创建事件类
public static class MessageEvent { /* Additional fields if needed */ }
  1. 在需要订阅事件的地方,声明订阅方法并注册EventBus。
@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {
    // Do something
}
public class EventBusActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    @Override
    protected void onStart() {
        super.onStart();
        //注册EventBus
        EventBus.getDefault().register(this);
    }
 
    //接收事件
    @Subscribe(threadMode = ThreadMode.POSTING, sticky = true, priority = 1)
    public void onReceiveMsg(MessageEvent message){
        Log.e("EventBus_Subscriber", "onReceiveMsg_POSTING: " + message.toString());
    }
 
    //接收事件
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 1)
    public void onReceiveMsg1(MessageEvent message){
        Log.e("EventBus_Subscriber", "onReceiveMsg_MAIN: " + message.toString());
    }
 
    //接收事件
    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED, sticky = true, priority = 1)
    public void onReceiveMsg2(MessageEvent message){
        Log.e("EventBus_Subscriber", "onReceiveMsg_MAIN_ORDERED: " + message.toString());
    }
 
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //取消事件
        EventBus.getDefault().unregister(this);
    }
}
  1. 提交订阅事件
@OnClick(R2.id.send_event_common)
public void clickCommon(){
    MessageEvent message = new MessageEvent(1, "这是一条普通事件");
    EventBus.getDefault().post(message);
}
 
@OnClick(R2.id.send_event_sticky)
public void clickSticky(){
    MessageEvent message = new MessageEvent(1, "这是一条黏性事件");
    EventBus.getDefault().postSticky(message);
}

Subcribe注解

Subscribe是EventBus自定义的注解,共有三个参数(可选):threadMode、boolean sticky、int priority。 完整的写法如下:

@Subscribe(threadMode = ThreadMode.MAIN,sticky = true,priority = 1)
public void onReceiveMsg(MessageEvent message) {
    Log.e(TAG, "onReceiveMsg: " + message.toString());
}

priority

priority是优先级,是一个int类型,默认值为0。值越大,优先级越高,越优先接收到事件。

值得注意的是,只有在post事件和事件接收处理,处于同一个线程环境的时候,才有意义。

sticky

sticky是一个boolean类型,默认值为false,默认不开启黏性sticky特性,那么什么是sticky特性呢?

上面的例子都是对订阅者 (接收事件) 先进行注册,然后在进行post事件。

那么sticky的作用就是:订阅者可以先不进行注册,如果post事件已经发出,再注册订阅者,同样可以接收到事件,并进行处理。

ThreadMode 模式

POSITING:订阅者将在发布事件的同一线程中被直接调用。这是默认值。事件交付意味着最少的开销,因为它完全避免了线程切换。因此,对于已知可以在很短时间内完成而不需要主线程的简单任务,推荐使用这种模式。使用此模式的事件处理程序必须快速返回,以避免阻塞发布线程(可能是主线程)。

MAIN:在Android上,订阅者将在Android的主线程(UI线程)中被调用。如果发布线程是主线程,将直接调用订阅者方法,阻塞发布线程。否则,事件将排队等待交付(非阻塞)。使用此模式的订阅者必须快速返回以避免阻塞主线程。如果不是在Android上,行为与POSITING相同。

MAIN_ORDERED:在Android上,订阅者将在Android的主线程(UI线程)中被调用。与MAIN不同的是,事件将始终排队等待交付。这确保了post调用是非阻塞的。

BACKGROUND:在Android上,订阅者将在后台线程中被调用。如果发布线程不是主线程,订阅者方法将在发布线程中直接调用。如果发布线程是主线程,EventBus使用一个后台线程,它将按顺序传递所有事件。使用此模式的订阅者应尽量快速返回,以避免阻塞后台线程。如果不是在Android上,总是使用一个后台线程。

ASYNC:订阅服务器将在单独的线程中调用。这始终独立于发布线程和主线程。使用此模式发布事件从不等待订阅者方法。如果订阅者方法的执行可能需要一些时间,例如网络访问,则应该使用此模式。避免同时触发大量长时间运行的异步订阅者方法,以限制并发线程的数量。EventBus使用线程池来有效地重用已完成的异步订阅者通知中的线程。

/**
 * Each subscriber method has a thread mode, which determines in which thread the method is to be called by EventBus.
 * EventBus takes care of threading independently from the posting thread.
 * 
 * @see EventBus#register(Object)
 * @author Markus
 */
public enum ThreadMode {
    /**
     * Subscriber will be called directly 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 in 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,

    /**
     * On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is
     * the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event
     * is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread.
     * If not on Android, behaves the same as {@link #POSTING}.
     */
    MAIN,

    /**
     * On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN},
     * the event will always be queued for delivery. This ensures that the post call is non-blocking.
     */
    MAIN_ORDERED,

    /**
     * On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber 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. Subscribers using this mode should try to
     * return quickly to avoid blocking the background thread. If not on Android, always uses a background thread.
     */
    BACKGROUND,

    /**
     * Subscriber will be called in a separate thread. This is always independent from the posting thread and the
     * main thread. Posting events never wait for subscriber methods using this mode. Subscriber 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 subscriber methods at the same time to limit the number of concurrent threads. EventBus
     * uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications.
     */
    ASYNC
}

相关文档

相关推荐

  1. 【17】Android 线通信(二) - Handler

    2024-06-06 18:26:03       21 阅读
  2. 【18】Android 线通信(三) - Handler

    2024-06-06 18:26:03       20 阅读
  3. Android基础-进程通信

    2024-06-06 18:26:03       29 阅读
  4. C# BlockingCollection实现线通信

    2024-06-06 18:26:03       60 阅读
  5. C# Channel实现线通信

    2024-06-06 18:26:03       52 阅读
  6. Android中线通信-Handler

    2024-06-06 18:26:03       53 阅读
  7. Android中的进程通讯

    2024-06-06 18:26:03       42 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-06 18:26:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-06 18:26:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-06-06 18:26:03       87 阅读
  4. Python语言-面向对象

    2024-06-06 18:26:03       96 阅读

热门阅读

  1. text2sql、nl2sql框架总结

    2024-06-06 18:26:03       25 阅读
  2. 贪心策略:FatMouse‘ Trade

    2024-06-06 18:26:03       25 阅读
  3. 安卓自动化之minicap截图

    2024-06-06 18:26:03       31 阅读
  4. 边缘计算:推动智能时代的前沿技术

    2024-06-06 18:26:03       29 阅读
  5. 【面结构光三维重建】1.双目系统的标定

    2024-06-06 18:26:03       32 阅读
  6. 解决splice改变原数组的BUG!

    2024-06-06 18:26:03       30 阅读
  7. Liunx启动oracle 、redis命令

    2024-06-06 18:26:03       25 阅读
  8. RabbitMQ简单使用方法,以异步处理日志为例:

    2024-06-06 18:26:03       30 阅读
  9. Spring类加载机制揭秘:深度解析“卸载”阶段

    2024-06-06 18:26:03       32 阅读
  10. SpringBoot整合Rabbitmq

    2024-06-06 18:26:03       27 阅读