RxBus

通过RxJava实现Rxbus。

相信大家已经非常熟悉EventBus了。最近正在学习Rxjava,如果在项目中已经使用了Rxjava,使用RxBus来代替EventBus应该是不错的选择。

RxJava最核心的两个东西是Observables(被观察者,事件源)和Subscribers(观察者)。Observables发出一系列事件,Subscribers处理这些事件。

RxBus工作原理

直接看代码

Note that it is important to subscribe to the exact same rxBus instance that was used to post the events

采用单例模式来保证rxBus对象一致

public class RxBus {

    private static RxBus rxBus;
private final Subject<Object, Object> _bus = new SerializedSubject<>(PublishSubject.create()); private RxBus() {
} public static RxBus getInstance() {
if (rxBus == null) {
synchronized (RxBus.class) {
if (rxBus == null) {
rxBus = new RxBus();
}
}
}
return rxBus;
} public void send(Object o) {
_bus.onNext(o);
} public Observable<Object> toObserverable() {
return _bus;
}
}

Activity中发送事件

public void sendTap(View view){
RxBus.getInstance().send(new TapEvent());
} public void sendOther(View view){
RxBus.getInstance().send(new OtherEvent());
}

Fragment中接收事件

 RxBus.getInstance().toObserverable()
.subscribe(new Action1<Object>() {
@Override
public void call(Object o) {
if (o instanceof TapEvent) {
textView.setText("tap");
} else if (o instanceof OtherEvent) {
textView.setText("other");
}
}
});

效果

效果图

以上就是使用Rxjava简单实现RxBus的功能,当然这还远远不够

RxBus升级

在具体使用过程中总会碰到各种各样的问题

场景1
我在上一个项目中实现了无限轮播的功能,并且希望轮播图在用户滑动、不可见、以及程序在后台休眠时都停止滚动,这时候就希望EventBus及时的传递这3种状态,为此我需要写slideEvent、visibleEvent、aliveEvent3个类,虽然他们都需要传递一个简单的Boolen值。

解决方案
创建一个Event“管家”
类似key-value的方式,每个事件都有自己的唯一的Code,接收事件时根据Code返回对应的content

public class Events<T> {

    //所有事件的CODE
public static final int TAP = ; //点击事件
public static final int OTHER = ; //其它事件 //枚举
@IntDef({TAP, OTHER})
@Retention(RetentionPolicy.SOURCE)
public @interface EventCode {} public @Events.EventCode int code;
public T content; public static <O> Events<O> setContent(O t) {
Events<O> events = new Events<>();
events.content = t;
return events;
} public <T> T getContent() {
return (T) content;
} }
场景2
怎么又内存泄漏了?

每个人在开发过程中,或多或少都会碰到内存泄漏的的问题,我一直有一个天真的想法,RxJava那么牛逼,是不是能无声无息地就能解决内存泄漏的问题了,答案是否定的。

我看了不少有关RxJava的文章,都会提到
一定要记得在生命周期结束的地方取消订阅事件,防止RxJava可能会引起的内存泄漏问题。

你可以

@Overrideprotected void onDestroy() {
super.onDestroy();
if(!rxSubscription.isUnsubscribed()) {
rxSubscription.unsubscribe();
}
}

又或者

使用CompositeSubscription把 Subscription 收集到一起,方便 Activity(基类) 销毁时取消订阅,防止内存泄漏。

前者可以在任一生命周期阶段取消订阅,缺点是每个acivity/fragment都要重写方法。

后者可以写在BaseActivity(大家都不会陌生),每个activity都能用,缺点是不够灵活。

以上两种方法似乎都欠缺点意思,所幸Rx家族”人丁兴旺“,早已想好了解决方案
RxLifecycle

一、bindToLifecycle()方法
在子类使用Observable中的compose操作符,调用,完成Observable发布的事件和当前的组件绑定,实现生命周期同步。从而实现当前组件生命周期结束时,自动取消对Observable订阅。
Observable.interval(, TimeUnit.SECONDS)
.compose(this.bindToLifecycle())
.subscribe(new Action1<Long>() {
@Override
public void call(Long num) {
Log.i(TAG, " " +num);
}
});
二、bindUntilEvent() 方法
使用ActivityEvent类,其中的CREATE、START、 RESUME、PAUSE、STOP、 DESTROY分别对应生命周期内的方法。使用bindUntilEvent指定在哪个生命周期方法调用时取消订阅。
public enum ActivityEvent {

    CREATE,
START,
RESUME,
PAUSE,
STOP,
DESTROY }
public enum FragmentEvent {

    ATTACH,
CREATE,
CREATE_VIEW,
START,
RESUME,
PAUSE,
STOP,
DESTROY_VIEW,
DESTROY,
DETACH }

组装零件

public class RxBus {

    private static RxBus rxBus;
private final Subject<Events<?>, Events<?>> _bus = new SerializedSubject<>(PublishSubject.<Events<?>>create()); private RxBus(){} public static RxBus getInstance(){
if (rxBus == null){
synchronized (RxBus.class){
if (rxBus == null){
rxBus = new RxBus();
}
}
}
return rxBus;
} public void send(Events<?> o) {
_bus.onNext(o);
} public void send(@Events.EventCode int code, Object content){
Events<Object> event = new Events<>();
event.code = code;
event.content = content;
send(event);
} public Observable<Events<?>> toObservable() {
return _bus;
} public static SubscriberBuilder with(FragmentLifecycleProvider provider){
return new SubscriberBuilder(provider);
} public static SubscriberBuilder with(ActivityLifecycleProvider provider){
return new SubscriberBuilder(provider);
} public static class SubscriberBuilder{ private FragmentLifecycleProvider mFragLifecycleProvider;
private ActivityLifecycleProvider mActLifecycleProvider;
private FragmentEvent mFragmentEndEvent;
private ActivityEvent mActivityEndEvent;
private int event;
private Action1<? super Events<?>> onNext;
private Action1<Throwable> onError; public SubscriberBuilder(FragmentLifecycleProvider provider) {
this.mFragLifecycleProvider = provider;
} public SubscriberBuilder(ActivityLifecycleProvider provider){
this.mActLifecycleProvider = provider;
} public SubscriberBuilder setEvent(@Events.EventCode int event){
this.event = event;
return this;
} public SubscriberBuilder setEndEvent(FragmentEvent event){
this.mFragmentEndEvent = event;
return this;
} public SubscriberBuilder setEndEvent(ActivityEvent event){
this.mActivityEndEvent = event;
return this;
} public SubscriberBuilder onNext(Action1<? super Events<?>> action){
this.onNext = action;
return this;
} public SubscriberBuilder onError(Action1<Throwable> action){
this.onError = action;
return this;
} public void create(){
_create();
} public Subscription _create(){
if (mFragLifecycleProvider!=null){
return RxBus.getInstance().toObservable()
.compose(mFragmentEndEvent == null ? mFragLifecycleProvider.bindToLifecycle() :mFragLifecycleProvider.<Events<?>>bindUntilEvent(mFragmentEndEvent)) // 绑定生命周期
.filter(new Func1<Events<?>, Boolean>() {
@Override
public Boolean call(Events<?> events) {
return events.code == event;
}
}) //过滤 根据code判断返回事件
.subscribe(onNext, onError == null ? new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
} : onError);
}
if (mActLifecycleProvider!=null){
return RxBus.getInstance().toObservable()
.compose(mActivityEndEvent == null ? mActLifecycleProvider.bindToLifecycle() :mActLifecycleProvider.<Events<?>>bindUntilEvent(mActivityEndEvent))
.filter(new Func1<Events<?>, Boolean>() {
@Override
public Boolean call(Events<?> events) {
return events.code == event;
}
})
.subscribe(onNext, onError == null ? (Action1<Throwable>) new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
} : onError);
}
return null;
}
}
}

新BUS上路

依然使用前面的例子

Activity中发送事件

 public void sendTap(View view){
RxBus.getInstance().send(Events.TAP, "Tap传了一个String");
} public void sendOther(View view){
RxBus.getInstance().send(Events.OTHER, null);
// RxBus.getInstance().send(Events.OTHER, new OtherEvent("Cloud", 25));
}

Fragment中接收事件

fragment需要继承RxLifecycle对应组件

public class BlankFragment extends RxFragment {}
 RxBus.with(this)
.setEvent(Events.TAP)
// .setEndEvent(FragmentEvent.DESTROY_VIEW) //不设置默认与fragment生命周期同步
.onNext(new Action1<Events<?>>() {
@Override
public void call(Events<?> events) {
String content = events.getContent();
textView.setText(content);
}
})
.create(); RxBus.with(this)
.setEvent(Events.OTHER)
.setEndEvent(FragmentEvent.DESTROY_VIEW) //不设置默认与fragment生命周期同步
.onNext(new Action1<Events<?>>() {
@Override
public void call(Events<?> events) {
OtherEvent event = events.getContent();
textView.setText("Name: " + event.getName() + ",Age: "+ event.getAge());
}
})
.onError(new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
textView.setText(throwable.toString());
}
}) // 异常处理,默认捕获异常,不做处理,程序不会crash。
.create();

效果

normal.gif

完整代码,请移步

参考资料

Android 打造属于自己的RxBus的更多相关文章

  1. Android 打造炫目的圆形菜单 秒秒钟高仿建行圆形菜单

    原文:Android 打造炫目的圆形菜单 秒秒钟高仿建行圆形菜单 转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43131133, ...

  2. Android 打造自己的ImageLoader

    Android 打造自己的ImageLoader 学习和参考 Android开发艺术探索 https://blog.csdn.net/column/details/15318.html 郭霖大神的Gl ...

  3. Android 打造完美的侧滑菜单/侧滑View控件

    概述 Android 打造完美的侧滑菜单/侧滑View控件,完全自定义实现,支持左右两个方向弹出,代码高度简洁流畅,兼容性高,控件实用方便. 详细 代码下载:http://www.demodashi. ...

  4. Android打造属于自己的数据库操作类。

    1.概述 开发Android的同学都知道sdk已经为我们提供了一个SQLiteOpenHelper类来创建和管理SQLite数据库,通过写一个子类去继承它,就可以方便的创建.管理数据库.但是当我们需要 ...

  5. android打造万能的适配器(转)

    荒废了两天,今天与大家分享一个ListView的适配器 前段时间在学习慕课网的视频,觉得这种实现方式较好,便记录了下来,最近的项目中也使用了多次,节省了大量的代码,特此拿来与大家分享一下. 还是先看图 ...

  6. Android 打造形形色色的进度条 实现可以如此简单

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43371299 ,本文出自:[张鸿洋的博客] 1.概述 最近需要用进度条,秉着不重 ...

  7. Android 打造任意层级树形控件 考验你的数据结构和设计

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40212367,本文出自:[张鸿洋的博客] 1.概述 大家在项目中或多或少的可能会 ...

  8. Android 打造编译时注解解析框架 这只是一个开始

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43452969 ,本文出自:[张鸿洋的博客] 1.概述 记得很久以前,写过几篇博客 ...

  9. Android 打造任意层级树形控件 考验你的数据结构和设计

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40212367,本文出自:[张鸿洋的博客] 1.概述 大家在项目中或多或少的可能会 ...

随机推荐

  1. android自己定义刷新类控件

    android尽管定义了种类很丰富的控件.可是有的时候这些自己定义的控件还是不能满足我的要求,为了可以适配很多其它的需求,我们须要在原有的基础上进行自己定义控件. 今天我向大家介绍的就是android ...

  2. hdu 思维风暴

    点击打开链接 偶然在杭电上看到的题目,数学题.好像是一道六年级奥赛题目,反正我是没有想出来,也知道往那上面想.就是找不到规律啊.学习了网上的方法, 这道题须要求出来多添加的点,就是与之前每条边添加的点 ...

  3. 为什么Java里的Arrays.asList不能用add和remove方法?

    在平时的开发过程中,我们知道能够将一个Array的对象转化为List.这种操作,我们仅仅要採用Arrays.asList这种方法即可了.笔者前段时间一直用这种方法,有一天,我发现通过Arrays.as ...

  4. Android——bootchart

    bootchart:android原生自带的开机性能查看机制.通过收集android开机过程中的各种log数据,终于能够图表的形式展现各个进程在开机过程中的性能.(博客不能断-) 撰写不易,转载需注明 ...

  5. nyoj--38--布线问题(克鲁斯卡尔)

    布线问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一种布线方式,该布线方式需要满足以下条件: 1.把所有的 ...

  6. React开发实时聊天招聘工具 -第六章 登陆注册(2)

    1.bodyParser和cookieParser:   const bodyParser = require('body-parser') const cookieParser = require( ...

  7. HTML5吃豆豆游戏开发实战(一)使用Canvas绘制游戏主角

    近期在学习HTML5.爱因斯坦曾说过,"最好的学习就是自己去经历". 于是.我想在学习HTML5的同一时候.做一款简单的小游戏,这样学习起来也会非常有趣的.我想做的是曾经小时候玩儿 ...

  8. 13.2 UPDATE

    13.2 UPDATE正在更新内容.请稍后

  9. 设计模式之Build(生成者模式)

    一.生成器模式的定义: 生成器模式也称为建造者模式.生成器模式的意图在于将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示(GoF).在软件设计中,有时候面临着一个非常复杂的对象的创 ...

  10. qgis显示引擎研究(一)

    作者:朱金灿 来源:http://blog.csdn.net/clever101 Qgis是一个著名的开源地理信息系统软件.今天研究了一下它的显示那一块,算是有一点眉目了. 在Windows环境下所有 ...