eventbus java_EventBus 3 全解

EventBus 3 全解

[TOC]

使用

一个基于观察者模式的事件发布/订阅框架. 用于模块间通信和解耦, 使用方便,性能高.

基本使用

1. gradle导入依赖库

implementation 'org.greenrobot:eventbus:3.1.1'

2. 定义事件类

public class MessageEvent {

public final String message;

public MessageEvent(String message) {

this.message = message;

}

}

3. 标记订阅方法. 当自定义事件发布后,此方法会被调用.

// This method will be called when a MessageEvent is posted (in the UI thread for Toast)

@Subscribe(threadMode = ThreadMode.MAIN)

public void onMessageEvent(MessageEvent event) {

Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();

}

// This method will be called when a SomeOtherEvent is posted

@Subscribe

public void handleSomethingElse(SomeOtherEvent event) {

doSomethingWith(event);

}

3.1 注册

@Override

public void onStart() {

super.onStart();

EventBus.getDefault().register(this);

}

3.2 注销

@Override

public void onStop() {

super.onStop();

EventBus.getDefault().unregister(this);

}

4. 发送事件

EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

5. 混淆

-keepattributes *Annotation*

-keepclassmembers class * {

@org.greenrobot.eventbus.Subscribe ;

}

-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor

-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {

(java.lang.Throwable);

}

Android平台最佳实践

​ 使用Subscriber Index , 在编译时为注册类和订阅构建了一个索引, 这样不必在运行时通过反射寻找订阅方法了. 对比入下图:

50dfcaa268a233f9079e10e49202590c.png

生成索引, gradle配置如下:

1. 借助AnnotationProcessor

android {

defaultConfig {

javaCompileOptions {

annotationProcessorOptions {

arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ]

}

}

}

}

dependencies {

implementation 'org.greenrobot:eventbus:3.1.1'

annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'

}

2. 如果使用kotlin , 使用kapt替代annotationProcessor

apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied

dependencies {

implementation 'org.greenrobot:eventbus:3.1.1'

kapt 'org.greenrobot:eventbus-annotation-processor:3.1.1'

}

kapt {

arguments {

arg('eventBusIndex', 'com.example.myapp.MyEventBusIndex')

}

}

3. 如果gradle版本小于2.2, 可以使用android-apt

buildscript {

dependencies {

classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

}

}

apply plugin: 'com.neenbedankt.android-apt'

dependencies {

compile 'org.greenrobot:eventbus:3.1.1'

apt 'org.greenrobot:eventbus-annotation-processor:3.1.1'

}

apt {

arguments {

eventBusIndex "com.example.myapp.MyEventBusIndex"

}

}

> 截止2019年9月20日, gradle配置用第一种就可以, 如果有特殊情况, 参考2, 3. 编译成功后, 会在如下目录生成.\app\build\generated\source\apt\debug\com\example\myapp\MyEventBusIndex.java , 如果没报错, 也没生成, 删掉build 文件夹, 再来一次.

使用索引

方式一 :

EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();

方式二 :

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

// Now the default instance uses the given index. Use it like this:

EventBus eventBus = EventBus.getDefault();

索引库

如果项目的依赖库中使用了索引, 可以添加多个索引:

EventBus eventBus = EventBus.builder()

.addIndex(new MyEventBusAppIndex())

.addIndex(new MyEventBusLibIndex()).build();

原理

%20raw.githubusercontent.com%20greenrobot%20eventbus%20master%20eventbus-publish-subscribe.png

流程图

注册

把事件和订阅者对应起来, 一个事件可以有多个订阅者, 一个订阅者可以订阅多个事件.

714fb516ba94d417e8dbe8dcf521546d.png

发送事件

根据事件, 找到订阅者,并执行订阅者对应的方法.

db5ac3ad31c19e22fd5329c73075cf20.png

注销

注销是移除订阅的操作.

根据注册的步骤可知:

typesBySubscriber = HashMap>

subscriptionsByEventType = HashMap>

有这样两个变量维持所有的事件和订阅者的对应关系, 所以循环找到传入的订阅者, 调用Map.remove().

设计模式

单例

一个Double Check:

public static EventBus getDefault() {

if (defaultInstance == null) {

synchronized (EventBus.class) {

if (defaultInstance == null) {

defaultInstance = new EventBus();

}

}

}

return defaultInstance;

}

构建者

EventBus(EventBusBuilder builder) {

logger = builder.getLogger();

subscriptionsByEventType = new HashMap<>();

typesBySubscriber = new HashMap<>();

stickyEvents = new ConcurrentHashMap<>();

mainThreadSupport = builder.getMainThreadSupport();

mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;

backgroundPoster = new BackgroundPoster(this);

asyncPoster = new AsyncPoster(this);

indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;

subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,

builder.strictMethodVerification, builder.ignoreGeneratedIndex);

logSubscriberExceptions = builder.logSubscriberExceptions;

logNoSubscriberMessages = builder.logNoSubscriberMessages;

sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;

sendNoSubscriberEvent = builder.sendNoSubscriberEvent;

throwSubscriberException = builder.throwSubscriberException;

eventInheritance = builder.eventInheritance;

executorService = builder.executorService;

}

观察者

不多说了.看上面原理图.

数据结构

ThreadLocal

问题

不支持跨进程

事件环路

把接收事件专门封装成一个子模块,同时考虑避免出现事件环路。

事件满天飞,维护困难

使用RxJava这样就可以使用RxBus了 :D

liveData

好东西, 和Android组件的生命周期紧密联系, 不需要手动处理生命周期, 因此不会造成内存泄露.

说实话整个Android Architecture Components都挺不错的, 就是出来的略晚了一些. 和现在流行的主流框架有些相持, 假以时日, 会越来越流行的. 事件,>订阅者,>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值