[Android]基于RxJava、RxAndroid的EventBus实现 - Android实例教程 - 安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户 - Powered by Discuz!
登录 立即注册
安币:

安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户

查看: 3345|回复: 27

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

[复制链接]

33

主题

41

帖子

87

安币

初级码农

Rank: 1

积分
41
发表于 2015-6-16 11:09:28 | 显示全部楼层 |阅读模式

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

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

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

RxBus代码如下:

[Java] 查看源文件 复制代码
/**
 * Author: wangjie
 * Email: [url=mailto:[email protected]][email protected][/url]
 * Date: 6/11/15.
 */
public class RxBus {
    private static final String TAG = RxBus.class.getSimpleName();
    private static RxBus instance;
    public static boolean DEBUG = false;

    public static synchronized RxBus get() {
        if (null == instance) {
            instance = new RxBus();
        }
        return instance;
    }

    private RxBus() {
    }

    private ConcurrentHashMap<Object, List<Subject>> subjectMapper = new ConcurrentHashMap<>();

    @SuppressWarnings("unchecked")
    public <T> Observable<T> register(@NonNull Object tag, @NonNull Class<T> clazz) {
        List<Subject> subjectList = subjectMapper.get(tag);
        if (null == subjectList) {
            subjectList = new ArrayList<>();
            subjectMapper.put(tag, subjectList);
        }

        Subject<T, T> subject;
        subjectList.add(subject = PublishSubject.create());
        if (DEBUG) Log.d(TAG, "[register]subjectMapper: " + subjectMapper);
        return subject;
    }

    public void unregister(@NonNull Object tag, @NonNull Observable observable) {
        List<Subject> subjects = subjectMapper.get(tag);
        if (null != subjects) {
            subjects.remove((Subject) observable);
            if (ABTextUtil.isEmpty(subjects)) {
                subjectMapper.remove(tag);
            }
        }

        if (DEBUG) Log.d(TAG, "[unregister]subjectMapper: " + subjectMapper);
    }

    public void post(@NonNull Object content) {
        post(content.getClass().getName(), content);
    }

    @SuppressWarnings("unchecked")
    public void post(@NonNull Object tag, @NonNull Object content) {
        List<Subject> subjectList = subjectMapper.get(tag);

        if (!ABTextUtil.isEmpty(subjectList)) {
            for (Subject subject : subjectList) {
                subject.onNext(content);
            }
        }
        if (DEBUG) Log.d(TAG, "[send]subjectMapper: " + subjectMapper);
    }
}

如上述代码,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类型的事件为例)

[Java] 查看源文件 复制代码
Observable<String> addOb = RxBus.get()
                .register("addFeedTag", String.class);

addOb.observeOn(AndroidSchedulers.mainThread())
                .subscribe(s -> {
                    // todo: Accept event and process here
                });

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

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

[Java] 查看源文件 复制代码
RxBus.get().post("addFeedTag", "hello RxBus!");

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

4. 反注册Observer:

[Java] 查看源文件 复制代码
RxBus.get().unregister("addFeedTag", addOb);

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

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

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

1. 注册Observer

这一步可以省略掉。

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

[Java] 查看源文件 复制代码
RxBus.get().post(new FeedItemClickEvent().setPosition(position).setFeed(feed));

3. 接收事件,然后处理

[Java] 查看源文件 复制代码
[url=home.php?mod=space&uid=469702]@accept[/url] public void onPostAccept(Object tag, FeedItemClickEvent event) {
   Logger.d(TAG, "onPostAccept event: " + event);
   Feed feed = event.getFeed();
   // 跳转到feed详情页面...
 }

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

注意:方法名可以任意

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

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

4. 反注册Observer

这一步也可以省略掉。

接收多种事件:

[Java] 查看源文件 复制代码
@Accept(            acceptScheduler = AcceptScheduler.NEW_THREAD,
            value = {
                    @AcceptType(tag = ActionEvent.CLOSE, clazz = String.class),
                    @AcceptType(tag = ActionEvent.BACK, clazz = String.class),
                    @AcceptType(tag = ActionEvent.EDIT, clazz = String.class),
                    @AcceptType(tag = ActionEvent.REFRESH, clazz = String.class)
            }
    )
    public void onPostAccept(Object tag, Object actionEvent) {
        Logger.d(TAG, "[ActionEvent]onPostAccept action event name: " + actionEvent);
        // todo: Accept event and process here (in new thread)
    }

[email protected]NEW_THREAD,指明方法运行在子线程中.

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

注解解释:@Accept注解

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

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

@AcceptType注解:

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

AcceptScheduler:

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

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

[Java] 查看源文件 复制代码
 /**
 * Author: wangjie
 * Email: [url=mailto:[email protected]][email protected][/url]
 * Date: 6/15/15.
 */
public class MyApplication extends Application {
    private Executor acceptExecutor = Executors.newCachedThreadPool();
    private Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void onCreate() {
        super.onCreate();
        RxBus.DEBUG = true;

        DefaultAcceptConfiguration.getInstance().registerAcceptConfiguration(new DefaultAcceptConfiguration.OnDefaultAcceptConfiguration() {
            @Override
            public Executor applyAcceptExecutor() {
                return acceptExecutor;
            }

            @Override
            public Handler applyAcceptHandler() {
                return handler;
            }
        });
    }
}

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

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


0

主题

0

帖子

-4

安币

初级码农

Rank: 1

积分
0
发表于 2015-6-22 02:12:42 | 显示全部楼层
谢谢楼主的辛苦分享

0

主题

0

帖子

-20

安币

初级码农

Rank: 1

积分
0
发表于 2015-6-27 17:15:56 | 显示全部楼层
学习了,这就去试试

0

主题

0

帖子

-25

安币

初级码农

Rank: 1

积分
0
发表于 2015-7-7 01:25:25 | 显示全部楼层
学习了!!!!

0

主题

0

帖子

-10

安币

初级码农

Rank: 1

积分
0
发表于 2015-7-16 09:34:54 | 显示全部楼层
支持一下,期待更多东西

0

主题

0

帖子

-4

安币

初级码农

Rank: 1

积分
0
发表于 2015-7-27 13:03:23 | 显示全部楼层
很不错的哦,支持,加油

0

主题

0

帖子

-10

安币

初级码农

Rank: 1

积分
0
发表于 2015-8-7 16:31:51 | 显示全部楼层
必须支持。。。。。。。

0

主题

0

帖子

-15

安币

初级码农

Rank: 1

积分
0
发表于 2015-8-24 16:21:59 | 显示全部楼层
不错不错 支持下
*滑动验证:
高级模式
B Color Image Link Quote Code Smilies |上传

本版积分规则

站长推荐

通过邮件订阅最新安卓weekly信息
上一条 /5 下一条
联系我们
关闭
合作电话:
13802416937
Email:
[email protected]
商务市场合作/投稿
问题反馈及帮助
联系我们

广告投放| Github|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

快速回复 返回顶部 返回列表