[Android]基于RxJava、RxAndroid的EventBus实现


Github:https://github.com/wangjiegulu/RxAndroidEventsSample

EventBus的作用是发布/订阅事件总线,因为项目中用到RxJava、RxAndroid,所以完全可以使用RxJava、RxAndroid来实现EventBus。

 

1. 编写RxBus,用于存储所有事件Subjects。

事件是传递的最小单位,可以把任何类作为一个事件。

RxBus代码如下:


 1 /*
2 Author: wangjie
3 Email: tiantian.china.2@gmail.com
4 Date: 6/11/15.
5 */
6 public class RxBus {
7 private static final String TAG = RxBus.class.getSimpleName();
8 private static RxBus instance;
9 public static boolean DEBUG = false;
10
11 public static synchronized RxBus get() {
12 if (null == instance) {
13 instance = new RxBus();
14 }
15 return instance;
16 }
17
18 private RxBus() {
19 }
20
21 private ConcurrentHashMap<Object, List<Subject>> subjectMapper = new ConcurrentHashMap<>();
22
23 @SuppressWarnings(“unchecked”)
24 public <T> Observable<T> register(@NonNull Object tag, @NonNull Class<T> clazz) {
25 List<Subject> subjectList = subjectMapper.get(tag);
26 if (null == subjectList) {
27 subjectList = new ArrayList<>();
28 subjectMapper.put(tag, subjectList);
29 }
30
31 Subject<T, T> subject;
32 subjectList.add(subject = PublishSubject.create());
33 if (DEBUG) Log.d(TAG, “[register]subjectMapper: “ + subjectMapper);
34 return subject;
35 }
36
37 public void unregister(@NonNull Object tag, @NonNull Observable observable) {
38 List<Subject> subjects = subjectMapper.get(tag);
39 if (null != subjects) {
40 subjects.remove((Subject) observable);
41 if (ABTextUtil.isEmpty(subjects)) {
42 subjectMapper.remove(tag);
43 }
44 }
45
46 if (DEBUG) Log.d(TAG, “[unregister]subjectMapper: “ + subjectMapper);
47 }
48
49 public void post(@NonNull Object content) {
50 post(content.getClass().getName(), content);
51 }
52
53 @SuppressWarnings(“unchecked”)
54 public void post(@NonNull Object tag, @NonNull Object content) {
55 List<Subject> subjectList = subjectMapper.get(tag);
56
57 if (!ABTextUtil.isEmpty(subjectList)) {
58 for (Subject subject : subjectList) {
59 subject.onNext(content);
60 }
61 }
62 if (DEBUG) Log.d(TAG, “[send]subjectMapper: “ + subjectMapper);
63 }
64 }

如上述代码,RxBus只提供了register、unregister、post三个方法。

这里又加入了一个tag的概念,也可以理解为channel,注册Subject、反注册Subject和post事件的时候都需要这个tag,只有tag一致才能正常接收到事件。

比如有一个事件类HelloEvent,这个事件的作用是接收到后toast一个提示“hello”,如果两个Activity都注册了这个HelloEvent事件,但是没有tag去限制,一旦post了一个helloEvent事件后,两个Activity都会收到这个事件,导致两个Activity都会toast。如果使用tag,post这个HelloEvent的时候可以设置这个tag,只有register时也使用了这个tag才会接收到这个event。

2. 在Present(如Activity的onCreate)中注册一个Observer(以下以发送一个String类型的事件为例)


1 Observable<String> addOb = RxBus.get()
2 .register(“addFeedTag”, String.class);
3
4 addOb.observeOn(AndroidSchedulers.mainThread())
5 .subscribe(s -> {
6 // todo: Accept event and process here
7 });

如上,注册了一个String类型的事件,事件的tag是“addFeedTag”,用来增加一个Feed。使用RxAndroid在Action1中处理接收到的这个事件。

3. 在任何地方发送一个事件:


RxBus.get().post(“addFeedTag”, “hello RxBus!”);

这里发送了一个tag为“addFeedTag”的String类型的事件。

4. 反注册Observer:


RxBus.get().unregister(“addFeedTag”, addOb);

注意:这里的Tag都为“addFeedTag”。

 

下面使用注解的方式更简单方便地使用RxBus(嗯-。-这里才是重点)。

首先来看下使用注解后的代码:

1. 注册Observer

这一步可以省略掉。

2. 发送一个事件(这里我们换一个事件:FeedItemClickEvent,我们定义这个事件是用来处理当Feed被点击后的事件)


RxBus.get().post(new FeedItemClickEvent().setPosition(position).setFeed(feed));

3. 接收事件,然后处理


1 @Accept
2 public void onPostAccept(Object tag, FeedItemClickEvent event) {
3   Logger.d(TAG, “onPostAccept event: “ + event);
4   Feed feed = event.getFeed();
5   // 跳转到feed详情页面…
6 }

如上,这里只需要编写一个方法,加上Accept注解,然后在方法中进行事件处理即可。

注意:方法名可以任意

方法参数一:必须为Object类型的tag;

方法参数二,如果这个方法只接收一种事件,则写明具体的事件类型,如上;如果这个方法接收多种事件,则类型需要为Object。

4. 反注册Observer

这一步也可以省略掉。

 

接收多种事件:


 1 @Accept(
2 acceptScheduler = AcceptScheduler.NEW_THREAD,
3 value = {
4 @AcceptType(tag = ActionEvent.CLOSE, clazz = String.class),
5 @AcceptType(tag = ActionEvent.BACK, clazz = String.class),
6 @AcceptType(tag = ActionEvent.EDIT, clazz = String.class),
7 @AcceptType(tag = ActionEvent.REFRESH, clazz = String.class)
8 }
9 )
10 public void onPostAccept(Object tag, Object actionEvent) {
11 Logger.d(TAG, “[ActionEvent]onPostAccept action event name: “ + actionEvent);
12 // todo: Accept event and process here (in new thread)
13 }

这里@Accept注解中设置了acceptScheduler为AcceptScheduler.NEW_THREAD,指明方法运行在子线程中.

value中指明了接收的事件类型,这里表示这个方法接收4种类型的事件:CLOSE, BACK, EDIT, REFRESH.

 

注解解释:

@Accept注解

acceptScheduler: 指定被注解的方法运行的Scheduler。

value[]: AcceptType注解数组,用于指定接收事件的tag和class。

 

@AcceptType注解:

tag: 接收事件的tag
clazz: 接收事件的类型

 

AcceptScheduler:

详情见:rx.schedulers.Schedulers和rx.android.schedulers.AndroidSchedulers

如果设置的是AcceptScheduler.EXECUTOR或AcceptScheduler.HANDLER,则需要在Application中配置Executor和Handler:


 1 /*
2 Author: wangjie
3 Email: tiantian.china.2@gmail.com
4 Date: 6/15/15.
5 */
6 public class MyApplication extends Application {
7 private Executor acceptExecutor = Executors.newCachedThreadPool();
8 private Handler handler = new Handler(Looper.getMainLooper());
9
10 @Override
11 public void onCreate() {
12 super.onCreate();
13 RxBus.DEBUG = true;
14
15 DefaultAcceptConfiguration.getInstance().registerAcceptConfiguration(new DefaultAcceptConfiguration.OnDefaultAcceptConfiguration() {
16 @Override
17 public Executor applyAcceptExecutor() {
18 return acceptExecutor;
19 }
20
21 @Override
22 public Handler applyAcceptHandler() {
23 return handler;
24 }
25 });
26 }
27 }

因为需要对Accept和AcceptType注解的解析,所以项目的BaseActivity需要使用AIAppCompatActivity,然后实现parserMethodAnnotations()方法,使用RxBusAnnotationManager对注解进行解析。

 

参考:http://nerds.weddingpartyapp.com/tech/2014/12/24/implementing-an-event-bus-with-rxjava-rxbus/

 



来源博客:Wang Jie's Blog
本文链接:https://blog.wangjiegulu.com/2015/06/15/Android-基于RxJava、RxAndroid的EventBus实现/
版权声明:本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处。