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

以下内容为原创,欢迎转载,转载请注明

来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4578699.html 

 

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/

 

时间: 2024-09-26 09:46:04

[Android]基于RxJava、RxAndroid的EventBus实现的相关文章

基于RxJava实现酷炫启动页_Android

前言 RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在 Java VM 上使用可观测的序列来组成异步的.基于事件的程序的库).这就是 RxJava ,概括得非常精准. 之前注意到coding APP启动页很是酷炫,今天我们使用RxJava和属性动画模仿实现其效果.

Android基于widget组件实现物体移动/控件拖动功能示例_Android

本文实例讲述了Android基于widget组件实现物体移动/控件拖动功能.分享给大家供大家参考,具体如下: package com.sky; import android.app.Activity; import android.os.Bundle; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickLi

Android基于反射技术实现的加减乘除运算示例_Android

本文实例讲述了Android基于反射技术实现的加减乘除运算.分享给大家供大家参考,具体如下: JAVA反射机制定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法

Android基于service实现音乐的后台播放功能示例_Android

本文实例讲述了Android基于service实现音乐的后台播放功能.分享给大家供大家参考,具体如下: Service是一个生命周期长且没有用户界面的程序,当程序在各个activity中切换的时候,我们可以利用service来实现背景音乐的播放,即使当程序退出到后台的时候,音乐依然在播放.下面我们给出具体例子的实现: 当然,首先要在资源文件夹中添加一首MP3歌曲: 要实现音乐的播放,需要在界面中放置两个按钮,用来控制音乐的播放和停止,通过使用startService和stopService来实现

Android基于Sensor感应器获取重力感应加速度的方法_Android

本文实例讲述了Android基于Sensor感应器获取重力感应加速度的方法.分享给大家供大家参考,具体如下: FETC项目指导老师提出了新的需求,想要在游戏地图中表现出用户用户当期移动的方向,再用GPS的话显然很不靠谱,所以想到了android强大的感应器... 很多移动设备都内置了感应器,android通过Sensor和SensorManager类抽象了这些感应器,通过这些类可以使用android设备的传感器 一 介绍Sensor类 SDK只有一句介绍"Class representing a

android基于天地图开发遇见的问题

问题描述 android基于天地图开发遇见的问题 这是activity界面的代码: package com.example.tianditu; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import com.tianditu.android.maps.GeoPoint; import com.tianditu.android.maps.MapActivity; import

Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果

转载请注明出处:http://blog.csdn.net/xiaanming/article/details/10163203 了解二维码这个东西还是从微信中,当时微信推出二维码扫描功能,自己感觉挺新颖的,从一张图片中扫一下竟然能直接加好友,不可思议啊,那时候还不了解二维码,呵呵,然后做项目的时候,老板说要加上二维码扫描功能,然后自己的屁颠屁颠的去百度,google啥的,发现很多朋友都有介绍二维码扫描的功能,然后我就跟着人家的介绍自己搞起了二维码扫描功能,跟着人家的帖子,很快我的项目就加入了扫描

Android 基于AOP监控之——AspectJ构建指南

如何使用 使用AspectJ做AOP可以做一些非侵入的AOP监控操作,方便简洁,功能强大,而且对目标工程没有侵入性,可以做切面的操作:监听方法耗时.输出日志.控制初入参数.进行运行时修改等等操作. 在Eclipse中已经有AJDT插件集成了AspectJ编译器的使用和关键字的声明.但是在Android Studio中没有这样的官方插件.因此,这里讲一下如何在Android Studio中使用AspectJ,来实现非侵入式的AOP监控.详细了解AspectJ的使用我在另一篇文章写了--Androi

我的Android进阶之旅------&amp;gt;Android基于HTTP协议的多线程断点下载器的实现

一.首先写这篇文章之前,要了解实现该Android多线程断点下载器的几个知识点  1.多线程下载的原理,如下图所示 注意:由于Android移动设备和PC机的处理器还是不能相比,所以开辟的子线程建议不要多于5条.当然现在某些高端机子的处理器能力比较强了,就可以多开辟几条子线程. 2.为了实现断点下载,采用数据库方式记录下载的进度,这样当你将该应用退出后,下次点击下载的时候,程序会去查看该下载链接是否存在下载记录,如果存在下载记录就会判断下载的进度,如何从上次下载的进度继续开始下载. 3.特别注意