美文网首页
进程内部消息处理之EventBus

进程内部消息处理之EventBus

作者: 郑在学_blog | 来源:发表于2017-10-19 10:16 被阅读0次
EventBus简介:

说到进程内部的消息通信,第一时间就会想到Intent,Handler,BroadCast。
EventBus是一款针对Android优化的发布/订阅事件总线。
主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。
要说明的是EventBus是一个进程范围内的发布/订阅时间总线,所以只能在一个进程内进行订阅和发布,如果你在新的进程里给Service/Activity发送消息,就无法收到消息了。
EventBus与LocalBroadcast 和观察者模式很类似,都可以实现进程内一对多的通信。

EventBus、广播和观察者的区别:

广播:
本地广播是三种方式中消耗时间、空间最多的一种方式,但也是同 android 相性最好的方式。因为广播属于 android 四大组件之一,在 BroadcastReceiver 中的 onReceive 方法中可以获得 Context、Intent 参数。持有这两个参数便可以调用许多 android sdk 中的方法。EventBus 和观察者,需要获得 Context 的话,往往都需要进行复杂的参数传递或者是依赖注入。
本地广播另外的一个优点是,许多系统级的事件都是使用广播来进行通知的,像常用的电量变化、网络状态变化、短信发送接收的状态等等。这就使得与 android 系统相关的通知,广播往往成了唯一的选择。
广播是重量级的、消耗资源较多的方式。广播的优势体现在它与 android sdk 链接的更紧密。对于不需要同 android 交互或是只做很少的交互的时候,就不推荐使用广播了。
并且在广播中有一个常见的坑:在 android 的 Application、Activity、Service、ContentProvider、BroadcastReceiver 中都可以获得对应的 Context,但它们并不完全相同。Activity 的 Context 所能做的事是最全的,而其它组件中的 Context 都或多或少的有着功能残缺。

Application和各个组件获取Context各自的功能

EventBus:
EventBus 作为 Android 开发中常用的框架,拥有着许多优点:调度灵活。不依赖于 Context,使用时无需像广播一样关注 Context 的注入与传递。父类对于通知的监听和处理可以继承给子类,这对于简化代码至关重要;通知的优先级,能够保证 Subscriber 关注最重要的通知;粘滞事件(sticky events)能够保证通知不会因 Subscriber 的不在场而忽略。可继承、优先级、粘滞,是 EventBus 比之于广播、观察者等方式最大的优点,它们使得创建结构良好组织紧密的通知系统成为可能。
使用简单。EventBus 的 Subscriber 注册非常简单,调用 eventBus 对象的 register 方法即可,如果不想创建 eventBus 还可以直接调用静态方法 EventBus.getDefault() 获取默认实例,Subscriber 接收到通知之后的操作放在 onEvent 方法里就行了。成为 Publisher 的过程就更简单了,只需要调用合适的 eventBus(自己创建的或是默认的)的 post 方法即可。

观察者模式:
由于观察者的实现比较简单,因此性能上是三者中最好的,但观察者难以控制通知的优先度,另外观察者模式要求观察者在事件发生时在场才能收到通知,这就使得观察者有可能遗漏事件也就是缺少Eventbus 优先级、粘滞事件的优点。
但有一个缺点是观察者独有的,那就是观察者可能会造成接口的膨胀。特别是当程序要求大量形式各异的通知,而程序员有没有做出良好的抽象时,代码中会包含大量的接口,接口数量的增长又会带来命名、注释等等一大堆问题。

Event的使用:

1.首先,在接受信息的Activity的OnCreate()和OnDestroy()方法注册和注销EventBus

EventBus.getDefault().register(this);/在OnCreate()中注册
EventBus.getDefault().unregister(this);//在OnDestroy()中注销

2.编写自定义类,里面封装好要发送和接受的信息

public class MainEvent{
 
         public String post = "";
     }

3.在接受信息的类中实现以下四个函数,各功能不同。EventBus3.0通过注解的方式,告知订阅函数运行在哪个线程中。

/**
     * 无论从那个线程发布的事件都会在UI线程中执行
     * ThreadMode.MAIN
     * @param event
     * 对应低版本的onEventMainThread方法
     */
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onEventMain(MainEvent event) {
        if(event != null){
            String frome = event.post;
            myTextView.setText(frome);
            Log.e("Test", "onEventMainThread = " + frome);
        }
    }

    /**
     * 无论从那个线程发布的事件,都在该线程中执行。
     * 所以需要注意,不能执行耗时操作,避免ANR
     * ThreadMode.POSTING
     * @param event
     * 对应低版本的onEvent
     */
    @Subscribe(threadMode = ThreadMode.POSTING, sticky = true)
    public void onEventPost(MainEvent event) {
        if(event != null){
            String frome = event.post;
            Log.e("Test", "onEventPostThread = " + frome);
        }
    }

    /**
     * 如果事件是从UI线程中发布出来,则在子线程中执行
     * 如果事件本身是从子线程中出来,则仍然在该子线程中执行
     * ThreadMode.BACKGROUND
     * @param event
     * 对应低版本的onEventBackgroundThread方法
     */
    @Subscribe(threadMode = ThreadMode.BACKGROUND, sticky = true)
    public void onEventBackground(MainEvent event) {
        if(event != null){
            String frome = event.post;
            Log.e("Test", "onEventBackgroundThread = " + frome);
        }
    }

    /**
     * 无论事件是从那个线程发布,都会另开一个线程执行
     * 所以该方法永远不会在UI线程中被执行
     * ThreadMode.ASYNC
     * 对应低版本的onEventAsync
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.ASYNC, sticky = true)
    public void onEventAsync(MainEvent event) {
        if(event != null){
            String frome = event.post;
            Log.e("Test", "onEventAsync = " + frome);
        }

四个函数的区别:

  • ThreadMode.MAIN:无论从那个线程发布的事件都会在UI线程中执行。所以不能执行耗时操作。
  • ThreadMode.POSTING:无论从那个线程发布的事件,都在该线程中执行,不能执行耗时操作,避免ANR。
  • ThreadMode.BACKGROUND:在子线程中执行,如果发布事件的线程是子线程就在该线程中执行。如果发布事件的线程不是子线程就创建一个子线程执行。
  • ThreadMode.ASYNC:另开一个线程执行。

5.发布事件

EventBus.getDefault().post(MainEvent);

6.添加依赖

compile 'org.greenrobot:eventbus:3.0.0'

另外,EventBus3.0可以使用优先级,取消事件和滞留事件

订阅事件的优先级:
@Subscribe(threadMode = ThreadMode.MAIN,priority = 100) //在ui线程执行 优先级100
    public void onDataSynEvent(DataSynEvent event) {
        Log.e(TAG, "event---->" + event.getCount());
    }

在注解中添加priority, 事件的优先级类似广播的优先级,优先级越高优先获得消息。

终止事件往下传递:

EventBus也有类似有序广播中的终止广播往下传递的操作。只需在订阅事件中添加语句:

EventBus.getDefault().cancelEventDelivery(event) ;//优先级高的订阅者可以终止事件往下传递
粘性事件:

类似广播分类中的粘性广播。
1.EventBus粘性事件的注册和注销与普通事件的注册和注销是一样的。
2.粘性事件需要添加注解sticky = true:

@Subscribe(threadMode = ThreadMode.MAIN,sticky = true) //在ui线程执行
    public void onDataSynEvent(DataSynEvent event) {
        Log.e(TAG, "event---->" + event.getCount());
    }

3.发布粘性事件

EventBus.getDefault().postSticky(new DataSynEvent());

4.如果不再需要该粘性事件我们可以移除

EventBus.getDefault().removeStickyEvents(new DataSynEvent());

5.如果要取消全部的粘性事件

EventBus.getDefault().removeAllStickyEvents(new DataSynEvent());
EventBus processor使用:

EventBus提供了一个EventBusAnnotationProcessor注解处理器来在编译期通过读取@Subscribe()注解并解析,
处理其中所包含的信息,然后生成java类来保存所有订阅者关于订阅的信息,这样就比在运行时使用反射来获得这些订阅者的信息速度要快.
简单来说就是Event Bus的加速器。

1.在build.gradle中添加如下配置

buildscript {
    dependencies {
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}
apply plugin: 'com.neenbedankt.android-apt'

dependencies {
    compile 'org.greenrobot:eventbus:3.0.0'
    apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
apt {
    arguments {
        eventBusIndex "com.whoislcj.eventbus.MyEventBusIndex"
    }
}

2.此时编译一次,自动生成生成索引类。在\build\generated\source\apt\PakageName\下看到通过注解分析生成的索引类。
3.在Application中启用加速模式,这样可以保证之后所有的EventBus都默认使用了加速模式。

EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();

具体一点:

public class MyApplication extends Application{
        private static Context context;
        @Override
        public void OnCreate(){
        EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();//在Application启动时加速
        context = getApplicationContext();
        }
        public static Context getContext(){
        return this.context;
        } 
}

参考文章:Android消息传递之EventBus 3.0使用详解

相关文章

  • 进程内部消息处理之EventBus

    EventBus简介: 说到进程内部的消息通信,第一时间就会想到Intent,Handler,BroadCast。...

  • Hermes跨进程通信原理解析

    简述 EventBus是事件总线,用来处理一些事件及时通知的,用来处理UI或数据。但是是单进程的,不能跨进程;说到...

  • 2019-04-23

    IPC android中eventbus能够实现进程间通信吗? 不可以用于多进程。EventBus貌似就是订阅者模...

  • Guava事件处理组件Eventbus使用入门

    1.说明 EventBus是Google Guava的事件处理机制,是设计模式中观察者模式的优雅实现,是一个进程内...

  • 一篇讲明白EventBus

    先说EventBus是什么: EventBus是 基于 订阅/发布 模式实现的 基于事件的异步分发处理系统。 ...

  • EventBus

    EventBus 3.0原理分析 HermesEventBus-饿了么开源的Android跨进程事件分发框架

  • 结合 AOP 轻松处理事件发布处理日志

    结合 AOP 轻松处理事件发布处理日志 Intro 前段时间,实现了 EventBus 以及 EventQueue...

  • EventBus源码解析(二)register与unregist

    前边文章主要跟大家大概讲了下EventBus的用法和注解,接下来则是从源码角度来看EventBus的内部处理 Ev...

  • 十四、EventBus

    EventBus优点:开销小,代码优雅。将发送者和接受者解耦 在EventBus3.0之后,事件处理的方法可以随便...

  • 进程处理

    os.getpod() #获取当前被执行程序的进程号 可以通过 multiprocessing.Value 和 ...

网友评论

      本文标题:进程内部消息处理之EventBus

      本文链接:https://www.haomeiwen.com/subject/shaeuxtx.html