rxbus 源码_Apollo-基于编译时注解处理的RxBus实现

在这篇教程中,我会向您展现如何实现一个编译时注解处理的RxBus(事件总线)。

开始之前

由于本篇文章会比较长,先容许我申明一些问题。

本篇文章是建立在您对Java Annotation以及Annotation Process 熟悉的基础之上,且本篇文章不讨论那些在运行时(Runtime)通过反射获取注解实现的RxBus,只讨论在编译时(Compile)完成的注解处理。

如果您实在没有耐心看完本篇文章,您可以点击 Apollo 访问Github上的开源库直接阅读我的源码,截止于2016年8月9日02:00,Github上Apollo的版本为0.1.2。

注意!目前 Apollo 仍处于非稳定版本,0.2版本之前不建议用于生产环境。

本篇文章以下提及到的RxBus的实现统称Apollo。

Compile-time的好处

目前Android中的一些流行库,如Dagger2,ButterKnife等都使用了Compile-time的注解处理,在编译时生成注入代码,来实现注入功能。其实通过Java的反射机制,也可以实现同样的功能,而且实现更加简单方便,不过反射机制的性能是一个问题,大量使用反射,往往是APP严重性能问题的根本原因。

而编译时注解处理只会在编译的时候占用开发资源,生成额外的代码来实现功能,这些通过注解处理生成的Java源代码会同其他手写的源文件一同被编译进APK。

Apollo的实现

目前常用的EventBus,Otto都是基于观察者(发布/订阅)模式。

所以,对于RxJava来说,它也可以实现事件总线,因为它本生就是基于观察者模式的。

我们知道RxJava中Subject同时充当了Observer和Observable的角色,我们即可以通过Subject来发布事件,同时也可以通过Subject来接收事件。

在RxJava提供的几个Subject中,PublishSubject最符合目前所需。PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者

在编写代码前,我希望Apollo能够做到以下几点:事件都有Tag作为唯一标识,

订阅者只接收对应Tag的事件

事件可以是任何对象

支持sticky event功能(因为在事件发送的时候,可能订阅此事件的Activity还没有启动)

Apollo是单例的

在满足以上条件后,先开始编写不带注解功能的Apollo:

package com.lsxiao.apllo;

import com.lsxiao.apllo.annotations.Receive;

import com.lsxiao.apllo.entity.SubscriberEvent;

import com.lsxiao.apllo.entity.SubscriptionBinder;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

import rx.Observable;

import rx.Scheduler;

import rx.functions.Func1;

import rx.schedulers.Schedulers;

import rx.subjects.PublishSubject;

import rx.subjects.SerializedSubject;

/**

* author lsxiao

* date 2016-05-09 17:27

*/

public class Apollo {

private SerializedSubject mPublishSubject;

private final Map mStickyEventMap;//用于保存stick事件

private static Apollo sInstance;

private Apollo() {

//SerializedSubject是线程安全的

//PublishSubject 会发送订阅者从订阅之后的事件序列,这意味着没订阅前的事件序列不会被发送到当前订阅者

mPublishSubject = new SerializedSubject<>(PublishSubject.create());

mStickyEventMap = new ConcurrentHashMap<>();

mBindTargetMap = new HashMap<>();

}

/**

* 返回一个Apollo的单例对象

*

* @return Apollo

*/

public synchronized static Apollo get() {

if (null == sInstance) {

sInstance = new Apollo();

}

return sInstance;

}

/**

* 判断是否有订阅者

*/

public boolean hasObservers() {

return mPublishSubject.hasObservers();

}

/**

* 根据tag和eventType获取指定类型的Sticky事件

*/

public T getStickyEvent(String tag, Class eventType) {

synchronized (mStickyEventMap) {

Object o = mStickyEventMap.get(tag).getData();

if (o.getClass().getCanonicalName().equals(eventType.getCanonicalName())) {

return eventType.cast(o);

}

}

return null;

}

/**

* 根据tag获取Sticky事件

*/

public Object getStickyEvent(String tag) {

synchronized (mStickyEventMap) {

return mStickyEventMap.get(tag) == null ? null : mStickyEventMap.get(tag).getData();

}

}

/**

* 移除指定eventType的Sticky事件

*/

public void removeStickyEvent(String tag) {

synchronized (mStickyEventMap) {

mStickyEventMap.remove(tag);

}

}

/**

* 移除指定eventType的Sticky事件

*/

public void removeStickyEvent(String[] tags) {

for (String tag : tags) {

removeStickyEvent(tag);

}

}

/**

* 移除所有的Sticky事件

*/

public void removeAllStickyEvents() {

synchronized (mStickyEventMap) {

mStickyEventMap.clear();

}

}

/**

* 发送event

*

* @param event SubscriberEvent

*/

private void send(SubscriberEvent event) {

mPublishSubject.onNext(event);

}

/**

* 发送event

*

* @param tag Tag

* @param actual 内容

*/

public void send(String tag, Object actual) {

SubscriberEvent event = new SubscriberEvent(tag, actual);

send(event);

}

/**

* 发送只有tag的event

*

* @param tag Tag

*/

public void send(String tag) {

send(tag, new Object());

}

/**

* 发送一个新Sticky事件

*/

public void sendSticky(String tag, Object actual) {

synchronized (mStickyEventMap) {

SubscriberEvent event = new SubscriberEvent(tag, actual, true);

mStickyEventMap.put(tag, event);

send(event);

}

}

public void sendSticky(String tag) {

synchronized (mStickyEventMap) {

SubscriberEvent event = new SubscriberEvent(tag, new Object(), true);

mStickyEventMap.put(tag, event);

mPublishSubject.onNext(event);

}

}

public Observable toObservable(final String tag) {

return toObservable(new String[]{tag}, Object.class);

}

public Observable toObservable(final String[] tags) {

return toObservable(tags, Object.class);

}

/**

* 返回普通事件类型的被观察者

*

* @param eventType 只接受eventType类型的响应,ofType = filter + cast

* @return Observable

*/

public Observable toObservable(final String tag, final Class eventType) {

return toObservable(new String[]{tag}, eventType);

}

public Observable toObservable(final String[] tags, final Class eventType) {

if (null == eventType) {

throw new NullPointerException("the eventType must be not null");

}

if (null == tags) {

throw new NullPointerException("the tags must be not null");

}

if (0 == tags.length) {

throw new IllegalArgumentException("the tags must be not empty");

}

return mPublishSubject

.filter(new Func1() {

@Override

public Boolean call(SubscriberEvent subscriberEvent) {

return Arrays.asList(tags).contains(subscriberEvent.getTag()) &&

//如果subscriberEvent.getData() = null,不用再去检查是不是特定类型或者其子类的实例

(subscriberEvent.getData() == null || eventType.isInstance(subscriberEvent.getData()));

}

})

.flatMap(new Func1>() {

@Override

public Observable call(SubscriberEvent subscriberEvent) {

return Observable.just(eventType.cast(subscriberEvent.getData()));

}

});

}

public Observable toObservableSticky(final String tag) {

return toObservable(new String[]{tag});

}

public Observable toObservableSticky(final String[] tags) {

return toObservableSticky(tags, Object.class);

}

/**

* 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者

*/

public Observable toObservableSticky(String tag, final Class eventType) {

return toObservableSticky(new String[]{tag}, eventType);

}

public Observable toObservableSticky(final String[] tags, final Class eventType) {

if (null == eventType) {

throw new NullPointerException("the eventType must be not null");

}

if (null == tags) {

throw new NullPointerException("the tags must be not null");

}

if (0 == tags.length) {

throw new IllegalArgumentException("the tags must be not empty");

}

synchronized (mStickyEventMap) {

//普通事件的被观察者

Observable observable = toObservable(tags, eventType);

final List stickyEventList = new ArrayList<>();

for (String tag : tags) {

//sticky事件

final SubscriberEvent event = mStickyEventMap.get(tag);

if (event != null) {

stickyEventList.add(mStickyEventMap.get(tag));

}

}

if (!stickyEventList.isEmpty()) {

//合并事件序列

return Observable.from(stickyEventList)

.flatMap(new Func1>() {

@Override

public Observable call(SubscriberEvent subscriberEvent) {

return Observable.just(eventType.cast(subscriberEvent.getData()));

}

}).mergeWith(observable);

} else {

return observable;

}

}

}

}上述代码中Subject同时充当了Observable以及Observer的功能,同时我们使用强制类型转换将PublishSubject转换成线程安全的SerializedSubject。

由于我们要实现通过tag接收event,以及sticky event功能,所以将tag和event封装成SubscriberEvent对象

我们在sendSticky()方法中将SubscriberEvent缓存起来,以便在有订阅者订阅sticky事件的时候,能够发送出去。

注意,toObservableSticky方法中对SubscriberEvent到源事件之间的转换,以及为了在接收到Sticky事件后还能继续接收普通事件,将普通的Observable和stickyObservable进行merge的操作。

思路分析

首先,创建一个同时可以充当Observable和Observer的Subject作为事件发布和订阅的桥梁。

在Acticity,Fragment等需要接收事件的类中实现订阅事件方法,例如:

Apollo.get().toObservable(User.class)

.subscribe(user -> {

//do something.

}, throwable -> {

throwable.printStackTrace();

}));

在我们需要发布事件的地方进行发布

Apollo.instance().send("SHOW_USER_INFO",user);

这样,在发布事件之前所有订阅了"SHOW_USER_INFO"普通事件的订阅者,都能够接收到"SHOW_USER_INFO"事件。

如果此事件发布之前订阅者还未订阅,我们可以发布一个Sticky事件:

Apollo.instance().sendSticky("SHOW_USER_INFO",user);

同时在订阅处通过toObservableSticky来订阅:

Apollo.get().toObservableSticky(User.class)

.subscribe(user -> {

//do something.

}, throwable -> {

throwable.printStackTrace();

}));

这样在订阅者订阅后,第一时间就会接收到此Sticky事件。注意,Sticky事件需要自行手动清除。

且注意在Activity/Fragment生命周期结束时候,一定要需要取消订阅,以防止RxJava引起的内存泄露。

@Override

protected void onDestroy() {

super.onDestroy();

if(!subscription.isUnsubscribed()) {

subscription.unsubscribe();

}

}

上述代码已经实现了一个简单的RxBus。

基于编译时注解处理的Apollo实现

还记得上面的Apollo的功能要求吗?事件都有Tag作为唯一标识,

订阅者只接收对应Tag的事件

事件可以是任何对象

支持sticky event功能(因为在事件发送的时候,可能订阅此事件的Activity还没有启动)

Apollo是单例的

现在,我要在之前的基础在给Apollo增加一些新的功能

我现在想通过Annotation来简化订阅代码,实现订阅指定tag事件:

@Receive(tag ="SHOW_USER_INFO")

public void receiveUser(User user) {

Log.d("apollo", "receive user event" + user.toString());

}

通过Annotation控制接收事件的类型(sticky,normal)

@Receive(tag ="SHOW_USER_INFO",type=Receive.Type.STICKY)

public void receiveUser(User user) {

Log.d("apollo", "receive user event" + user.toString());

}

通过Annotation控制调度器

@Receive(tag ="SHOW_USER_INFO",

subscribeOn=Receive.Thread.IO,

observeOn=Receive.Thread.Main)

public void receiveUser(User user) {

Log.d("apollo", "receive user event" + user.toString());

}

通过以下的形式来进行绑定和解绑

public abstract class BaseActivity extends AppCompatActivity {

private SubscriptionBinder mBinder;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(getLayoutId());

afterCreate(savedInstanceState);

//绑定

mBinder = Apollo.get().bind(this);

}

@Override

protected void onDestroy() {

super.onDestroy();

//解绑

mBinder.unbind();

}

protected abstract int getLayoutId();

protected abstract void afterCreate(Bundle savedInstanceState);

}

由于开篇已经说过本篇文章只介绍如何实现Complie-time的Apollo,所以这里不考虑Run-time的反射机制实现。

在开始编写complie-time Apollo之前,我们先回顾一下Dagger2和ButterKnife,当使用的时候至少都需要引入两个module,其中有一个module一般叫做compiler或者processor(以下统称processor),例如:

compile 'com.jakewharton:butterknife:8.2.1'

apt 'com.jakewharton:butterknife-compiler:8.2.1'

processor的作用是负责完成注解处理,生成代码。

同时由于编译时用于生成代码的processor我们是不需要打包进apk的,所以使用apt而不是complie命令。

在这里,我把整个Apollo分成两个部分:一个是核心代码部分,实现主要的功能,提供绑定接口的apollo module。

一个是解析所有我们需要Annotation,生成指定绑定代码的processor module。

在编写processor之前,其实apollo的逻辑之前基本上已经完成的差不多了,这里主要需要实现的还剩:apollo提供绑定接口,让processor生成的绑定代码实现接口,初始化的时候让apollo持有生成 的绑定接口实现类实例。这样就可以在BaseActivity中通过apollo.get.bind()方式进行绑定。

apollo提供RxJava的基本调度器,而AndroidSchedulers.mainThread()在初始化的时候作为参数传入。(由于apollo module是一个java library,不能依赖作为Android library的RxAndroid,所以main调度器需要初始化的时候传入,之后我会提及到为什么apollo和processor都只能是java library)

这里先给出SubscriberBinder接口:

public interface SubscriberBinder {

SubscriptionBinder bind(Object object);

}

接口很简单,只需要实现一个bind方法,并且返回SubscriptionBinder对象(注意和SubscriberBinder的区别)。

SubscriberBinder的实现(用于取消订阅)

public class SubscriptionBinder {

private CompositeSubscription mSubscription;

public SubscriptionBinder() {

mSubscription = new CompositeSubscription();

}

public void add(Subscription subscription) {

if (mSubscription == null) {

throw new IllegalAccessError("this binder has been unbinded");

}

if (subscription == null) {

throw new NullPointerException("subscription must be not null");

}

mSubscription.add(subscription);

}

public void unbind() {

if (mSubscription != null && !mSubscription.isUnsubscribed()) {

mSubscription.unsubscribe();

mSubscription = null;

}

}

}

给Apollo添加绑定方法

public SubscriptionBinder bind(Object o) {

if (null == o) {

throw new NullPointerException("object to bind must not be null");

}

return mSubscriberBinder.bind(o);

}绑定成功后,返回一个SubscriptionBinder对象,在生命周期结束的时候我们可以调用SubscriptionBinder.unbind();方法来解绑当前Activity或者Fragment中所有的订阅者。

processor实现

在写processor之前,首先要知道AbstractProcessor这个抽象处理器,每一个注解处理器都必须继承此处理器(下面会有很多引用解释,不过不会赘述):

package com.example;

public class ApolloAnnotationProcessor extends AbstractProcessor {

@Override

public synchronized void init(ProcessingEnvironment env){ }

@Override

public boolean process(Set extends TypeElement> annoations, RoundEnvironment env) { }

@Override

public Set getSupportedAnnotationTypes() { }

@Override

public SourceVersion getSupportedSourceVersion() { }

}init(ProcessingEnvironment env):-初始化操作的方法,RoundEnvironment会提供很多有用的工具类Elements、Types和Filer等

process(Set extends TypeElement> annoations, RoundEnvironment env):在这里进行注解的扫描,处理,Java代码的生成,是入口函数。注意!如果在此函数中,你生成了源代码,此process方法可能会被调用多次,因为你生成的源代码中可能也有会注解,process方法会继续对源代码文件进行处理,直至process中没有生成任何源文件。

getSupportedAnnotationTypes:返回需要处理的注解类型,也就是说注解处理器只处理那些注解,这里是必须指定的。

getSupportedSourceVersion():用来指定你使用的Java版本。通常这里返回SourceVersion.latestSupported()。在Java 7中,你也可以使用注解来代替getSupportedAnnotationTypes()和getSupportedSourceVersion(),像这样:

@SupportedSourceVersion(SourceVersion.latestSupported())

@SupportedAnnotationTypes({

// 合法注解全名的集合

})

public class MyProcessor extends AbstractProcessor {

@Override

public synchronized void init(ProcessingEnvironment env){ }

@Override

public boolean process(Set extends TypeElement> annoations, RoundEnvironment env) { }

}

因为兼容的原因,特别是针对Android平台,我建议使用重载getSupportedAnnotationTypes()和getSupportedSourceVersion()方法代替@SupportedAnnotationTypes和@SupportedSourceVersion。注册处理器为了让自定义的Processor生效呢,需要在在processor的java同级目录新建resources/META-INF/services/javax.annotation.processing.Processor文件

- com

-lsxiao

-apollo

-processor

-ApolloAnnotationProcessor.java

- META-INF

- services

- javax.annotation.processing.Processor

然后在javax.annotation.processing.Processor文件中指定自定义的处理器,如:

com.lsxiao.apollo.processor.ApolloAnnotationProcessor

多个处理器换行写。

然后执行gradle build即可。

如果你在编译时注解处理中更高效率的开发,而不是用字符串拼接来生成源文件,就需要用到如下几个类库:Android Studio原本是不支持注解处理器的, 但是用android-apt这个插件后, 我们就可以使用注解处理器了,

这个插件可以自动的帮你为生成的代码创建目录, 让生成的代码编译到APK里面去, 而且它还可以让最终编译出来的APK里面不包含注解处理器本身的代码,因为这部分代码只是编译的时候需要用来生成代码, 最终运行的时候是不需要的。 也就是说它主要有两个目的:

允许配置只在编译时作为注解处理器的依赖,而不添加到最后的APK或library

设置源路径,使注解处理器生成的代码能被Android Studio正确的引用那在什么情况下我们会需要使用它呢?当你需要引入Processor生成的源代码到你的代码中时。例如当你使用Dagger 2或AndroidAnnotaition.

该插件使得Android Studio可以配置生成资源的build path,避免IDE报错。

当使用apt添加添加依赖,它将不会被包含到最终的APK里。

Google Auto的主要作用是注解Processor类,并对其生成META-INF的配置信息, 可以让你不用去写META-INF这些配置文件,只要在自定义的Processor上面加上@AutoService(Processor.class)javapoet:A Java API for generating .java source files.可以更方便的生成代码,它可以帮助我们通过类调用的形式来生成代码。

ApolloAnnotationProcessor.java

@AutoService(Processor.class)

public class ApolloAnnotationProcessor extends AbstractProcessor {

private ReceiveAnnotationHandler mReceiveAnnotationHandler;

//init():初始化操作的方法,RoundEnvironment会提供很多有用的工具类Elements、Types和Filer等。

@Override

public synchronized void init(ProcessingEnvironment processingEnv) {

super.init(processingEnv);

Filer mFiler = processingEnv.getFiler();

Types mTypeUtil = processingEnv.getTypeUtils();

Elements mElementUtil = processingEnv.getElementUtils();

Messager mMessager = processingEnv.getMessager();

BaseHandler.init(mMessager, mTypeUtil, mElementUtil, mFiler);

mReceiveAnnotationHandler = new ReceiveAnnotationHandler();

}

//process()相当于每个处理器的主函数main()。在该方法中去扫描、评估、处理以及生成Java文件。

@Override

public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {

mReceiveAnnotationHandler.process(roundEnv);

return true;

}

/**

* 指定该注解处理器需要处理的注解类型

*

* @return 需要处理的注解类型名的集合Set

*/

@Override

public Set getSupportedAnnotationTypes() {

Set types = new HashSet<>();

types.add(com.lsxiao.apllo.annotations.Receive.class.getCanonicalName());

return types;

}

/**

* 指定使用的java版本。通常这里会直接放回SourceVersion.latestSupported()即可。

*

* @return SourceVersion

*/

@Override

public SourceVersion getSupportedSourceVersion() {

return SourceVersion.latestSupported();

}

}

ReceiveAnnotationHandler.java(把process里面解析Receive的任务抽离出来,方便以后增加注解后的扩展)

public class ReceiveAnnotationHandler extends BaseHandler {

private Map> mClassMethodMap = new HashMap<>();

//如果生成了新的源文件process()能够被调用多次,因为生成的源文件中可能会有注解,它们还将会被ApolloAnnotationProcessor处理。

//所以这里需要是个是否完成标志变量,避免重复处理注解 创建源文件造成异常

private boolean handleComplete = false;

@Override

public void process(RoundEnvironment roundEnv) {

if (handleComplete) {

return;

}

//单例变量

FieldSpec.Builder fieldBuilder = FieldSpec.builder(Apollo.SubscriberBinder.class, "sInstance", Modifier.PRIVATE, Modifier.STATIC);

//单例方法

MethodSpec.Builder instanceMethodBuilder = MethodSpec.methodBuilder("instance")

.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.SYNCHRONIZED)

.returns(Apollo.SubscriberBinder.class)

.beginControlFlow("if (null == sInstance)")

.addStatement("sInstance = new SubscriberBinderImplement()")

.endControlFlow()

.addStatement("return sInstance");

//绑定方法

MethodSpec.Builder bindMethodBuilder = MethodSpec.methodBuilder("bind")

.addModifiers(Modifier.PUBLIC)

.addAnnotation(Override.class)

.returns(SubscriptionBinder.class)

.addParameter(Object.class, "object")

.addStatement("final $T subscriptionBinder = new $T()", SubscriptionBinder.class, SubscriptionBinder.class);

for (Element element : roundEnv.getElementsAnnotatedWith(Receive.class)) {

//注解最最外侧必须是一个类

if (element.getEnclosingElement().getKind() != ElementKind.CLASS) {

//打印出错信息

error("@Receive must be wrapped by a class");

}

if (element.getKind() != ElementKind.METHOD) {

error("@Receive only support method!");

}

//转行成可执行element

ExecutableElement receiveMethodElement = (ExecutableElement) element;

//找到注解所属的类

TypeElement classElementAnnotationIn = (TypeElement) element.getEnclosingElement();

//获取类的完全限定名

final DeclaredType declaredType = getTypeUtil().getDeclaredType(classElementAnnotationIn);

List methodList = mClassMethodMap.get(declaredType);

if (methodList == null) {

methodList = new ArrayList<>();

mClassMethodMap.put(declaredType, methodList);

}

//存储方法

methodList.add(receiveMethodElement);

}

for (DeclaredType classTypeAnnotationIn : mClassMethodMap.keySet()) {

String receiveMethodInvoker = StrUtil.dot2Underline(classTypeAnnotationIn.toString());

bindMethodBuilder

.beginControlFlow("if(object.getClass().getCanonicalName().equals($S))", classTypeAnnotationIn.toString())

.addStatement("final $T $N=($T)object", classTypeAnnotationIn, receiveMethodInvoker, classTypeAnnotationIn);

for (ExecutableElement methodElement : mClassMethodMap.get(classTypeAnnotationIn)) {

//receive方法只能有一个变量

if (methodElement.getParameters().size() > 1) {

error("the " + methodElement.toString() + " method in " + classTypeAnnotationIn.toString() + " only support 1 parameter,but there are " + methodElement.getParameters().size());

}

//获取方法第一个变量

VariableElement eventVariable = methodElement.getParameters().get(0);

//获取tag值

String tag = methodElement.getAnnotation(Receive.class).tag();

Receive.Thread observeOn = methodElement.getAnnotation(Receive.class).observeOn();

Receive.Thread subscribeOn = methodElement.getAnnotation(Receive.class).subscribeOn();

//获取receiveMethod是否接收sticky event

boolean isSticky = methodElement.getAnnotation(Receive.class).type() == Receive.Type.STICKY;

String receiveMethod = methodElement.getSimpleName().toString();

String onSubscribeMethod = isSticky ? "toObservableSticky" : "toObservable";

String eventVariableClassType = eventVariable.asType().toString() + ".class";

String eventVariableClass = eventVariable.asType().toString();

String eventVariableInstance = eventVariable.getSimpleName().toString().toLowerCase();

bindMethodBuilder

.addStatement("subscriptionBinder.add($T.get().$N($S,$N).subscribeOn($T.get().getThread().get($N.$N)).observeOn($T.get().getThread().get($N.$N)).subscribe(" +

"new $T(){" +

"@Override " +

"public void call($N $N){" +

"$N.$N($N);" +

"}}," +

"new $T(){" +

"@Override " +

"public void call($T a){" +

"a.printStackTrace();" +

"}}" +

"))",

Apollo.class,

onSubscribeMethod,

tag,

eventVariableClassType,

Apollo.class,

Receive.Thread.class.getCanonicalName(),

subscribeOn.name(),

Apollo.class,

Receive.Thread.class.getCanonicalName(),

observeOn.name(),

Action1.class,

eventVariableClass,

eventVariableClass,

eventVariableInstance,

receiveMethodInvoker,

receiveMethod,

eventVariableInstance,

Action1.class,

Throwable.class,

Throwable.class);

}

bindMethodBuilder.endControlFlow();

}

bindMethodBuilder.addStatement("return subscriptionBinder");

TypeSpec subscriberClass = TypeSpec.classBuilder("SubscriberBinderImplement")

.addModifiers(Modifier.PUBLIC, Modifier.FINAL)

.addSuperinterface(Apollo.SubscriberBinder.class)

.addField(fieldBuilder.build())

.addMethod(instanceMethodBuilder.build())

.addMethod(bindMethodBuilder.build())

.build();

generateCode(subscriberClass);

}

private void generateCode(TypeSpec subscriberClass) {

JavaFile javaFile = JavaFile.builder("com.lsxiao.apollo.generate", subscriberClass)

.build();

try {

javaFile.writeTo(getFiler());

handleComplete = true;

} catch (IOException e) {

e.printStackTrace();

}

}

}上面的代码使用Javapoet完成了一个SubscriberBinder接口的实现类,提供了静态方法能够获取SubscriberBinderImplement单例。

被注解的方法只能接收一个事件参数

被注解的方法最外侧结点必须是一个类

根据注解的tag,type,以及thread分别为对应的方法订阅对应的tag事件,并且在输出的时候讲事件转换成发送时候的类型,最后在subscribeOn和observeO指定线程调度器。

最后demo中生成的源文件如下

public final class SubscriberBinderImplement implements Apollo.SubscriberBinder {

private static Apollo.SubscriberBinder sInstance;

public static synchronized Apollo.SubscriberBinder instance() {

if (null == sInstance) {

sInstance = new SubscriberBinderImplement();

}

return sInstance;

}

@Override

public SubscriptionBinder bind(Object object) {

final SubscriptionBinder subscriptionBinder = new SubscriptionBinder();

if (object.getClass().getCanonicalName().equals("com.lsxiao.apollo.demo.activity.MainActivity")) {

final MainActivity com_lsxiao_apollo_demo_activity_MainActivity = (MainActivity) object;

subscriptionBinder.add(Apollo.get().toObservable("event_show_book", com.lsxiao.apollo.demo.activity.MainActivity.Book.class).subscribeOn(Apollo.get().getThread().get(com.lsxiao.apllo.annotations.Receive.Thread.IO)).observeOn(Apollo.get().getThread().get(com.lsxiao.apllo.annotations.Receive.Thread.MAIN)).subscribe(new Action1() {

@Override

public void call(com.lsxiao.apollo.demo.activity.MainActivity.Book book) {

com_lsxiao_apollo_demo_activity_MainActivity.receiveBook(book);

}

}, new Action1() {

@Override

public void call(Throwable a) {

a.printStackTrace();

}

}));

subscriptionBinder.add(Apollo.get().toObservable("event_show_user", com.lsxiao.apollo.demo.activity.MainActivity.User.class).subscribeOn(Apollo.get().getThread().get(com.lsxiao.apllo.annotations.Receive.Thread.IO)).observeOn(Apollo.get().getThread().get(com.lsxiao.apllo.annotations.Receive.Thread.MAIN)).subscribe(new Action1() {

@Override

public void call(com.lsxiao.apollo.demo.activity.MainActivity.User user) {

com_lsxiao_apollo_demo_activity_MainActivity.receiveUser(user);

}

}, new Action1() {

@Override

public void call(Throwable a) {

a.printStackTrace();

}

}));

}

if (object.getClass().getCanonicalName().equals("com.lsxiao.apollo.demo.activity.BookActivity")) {

final BookActivity com_lsxiao_apollo_demo_activity_BookActivity = (BookActivity) object;

subscriptionBinder.add(Apollo.get().toObservableSticky("event_show_book", com.lsxiao.apollo.demo.activity.MainActivity.Book.class).subscribeOn(Apollo.get().getThread().get(com.lsxiao.apllo.annotations.Receive.Thread.IO)).observeOn(Apollo.get().getThread().get(com.lsxiao.apllo.annotations.Receive.Thread.MAIN)).subscribe(new Action1() {

@Override

public void call(com.lsxiao.apollo.demo.activity.MainActivity.Book book) {

com_lsxiao_apollo_demo_activity_BookActivity.receiveBook(book);

}

}, new Action1() {

@Override

public void call(Throwable a) {

a.printStackTrace();

}

}));

}

return subscriptionBinder;

}

}

初始化

public class App extends Application {

@Override

public void onCreate() {

super.onCreate();

Apollo.get().init(SubscriberBinderImplement.instance(), AndroidSchedulers.mainThread());

}

}以上就是整个Complie-time RxBus的整体实现,详细细节可以查看Apollo。

ps.注意!再次提醒目前 Apollo 仍处于非稳定版本,0.2版本之前不建议用于生产环境。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值