看上一篇博客,里面有很多牛人对RxJava分析的博客链接。
RxJava介绍
GitHub 主页上的自我介绍是 “a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)
RxJava 的本质可以压缩为异步这一个词。说到根上,它就是一个实现异步操作的库。
RxJava的好处就是简洁,就算在逻辑复杂的情况下,也能让代码一幕了然,代码逻辑清晰。
RxJava原理分析
RxJava的异步实现原理,是观察者模式的一种拓展。
观察者模式
- 具有观察者对象(A)和关注事件对象对象(B)
- A 需要对 B 的某种变化具有高度敏感,当 B 这中变化发生时 A 对象要立即做出反映
- A 可以通过注册(Register)或订阅(Subscribe)的方式告诉 B,当 B 发生某种变化是请通知 A 。(可以参考Android 中 View的点击事件设置
setOnClickListener()
)
RxJava的观察者模式
RxJava 作为一个工具库,使用的就是通用形式的观察者模式。
RxJava也存在Observer
(观察者)和 Observable
(关注事件对象),Observer
和 Observable
通过 subscribe()
方法实现订阅关系, 关注事件对象Observable
在发生指定动作的通知观察者 Observer
。
为了便于理解,Observable
(关注事件对象)可以想成关注事件对象
,当关注事件
发生后此对象立马通知观察者Observer
。
RxJava除了对应传统的回调onClick()
的方法onNext()
外,还有onCompleted()
、onError()
。
onNext()
:发出一个事件。onCompleted()
:事件队列完结。RxJava把所有事件当作一个队列,单独处理队列中的每个事件。当不再有新的onNext()
发出时,触发此方法。onError()
:事件队列异常。事件处理过程中出现异常的情况,此方法会触发,同时队列自动结束,不在允许有事件发出。
RxJava基本使用
实现个简单使用测试,将”One”、”Two”、”There”按顺序Toast打印出来。
创建Observable
(关注事件对象)
Observable
规定了事件触发的顺序和方式。下面创建一个关注事件对象对象并定义事件触发规则。
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("One");
subscriber.onNext("Two");
subscriber.onNext("There");
subscriber.onCompleted();
}
});
也可以使用下面的方式获取观察者对象
Observable<String> observable = Observable.just("One", "Two", "There");
String[] words = {"One", "Two", "There"};
Observable<String> observable = Observable.from(words);
这两种方式是系统帮你完成了创建关注事件对象。
//Observable.just() 调用 Observable.from()
public static <T> Observable<T> just(T t1, T t2) {
return from((T[])new Object[] { t1, t2 });
}
//Observable.from()
public static <T> Observable<T> from(T[] array) {
int n = array.length;
if (n == 0) {
return empty();
} else
if (n == 1) {
return just(array[0]);
}
//OnSubscribeFromArray 实现了 Observable.OnSubscribe 接口
//里面制定了简单的onNext()等触发规则
return create(new OnSubscribeFromArray<T>(array));
}
创建Observer
(观察者)
Observer
规定了事件触发后将执行的行为、动作。
Observer<String> observer = new Observer<String>() {
@Override
public void onCompleted() {
ZNotify.toast(mContext, "Completed");
}
@Override
public void onError(Throwable e) {
ZNotify.toast(mContext, "Error");
}
@Override
public void onNext(String s) {
ZNotify.toast(mContext, "item:" + s);
}
};
除了Observer
接口外,RxJava还内置了一个实现Observer
接口的抽象类:Subscriber
,新建Subscriber
观察者对象。
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
ZNotify.toast(mContext, "Completed");
}
@Override
public void onError(Throwable e) {
ZNotify.toast(mContext, "Error");
}
@Override
public void onNext(String s) {
ZNotify.toast(mContext, "item:" + s);
}
};
它们基本使用方式是一样的。在RxJava的Subscribe (订阅)过程中,Observer
会被先转化为Subscriber
再去使用,Subscriber
对Observer
接口进行了一些拓展。
isUnsubscribed()
:实现Subscription
接口。判断当前Observer
(观察者)是否取消订阅关系。用来判断是否有关注事件对象持有当前观察者的引用。unsubscribe()
:实现Subscription
接口。解除订阅关系释放引用,先用isUnsubscribed()
判断下。在subscribe()
后,Observable
持有Subscriber
的引用,这个引用不能及时释放会有内存泄漏的危险。所以在合适的地方调用unsubscribe()
解除引用。onStart()
:新增方法,事件发送前调用,可以进行准备工作。需要注意,此方法不一定在主线程中调用。如果需要指定线程进行准备工作,可以在doOnSubscribe()
方法中进行,下面介绍。
实现订阅关系
建立了Observable
和Observer
对象之后,我们可以调用subscribe()
方法确立它们之间的订阅关系,就可以工作了。
Subscription subscribe = observable.subscribe(observer);
或者
Subscription subscribe = observable.subscribe(subscriber);
通过subscribe()
方法确定订阅关系后会返回Subscription 接口对象subscribe 。
之前了解到所有的观察者对象在Subscribe (订阅)过程中会先被转化为Subscriber
再去使用,Subscriber
实现了接口Subscription 。
我们可以使用返回的Subscription接口对象在需要的时候调用unsubscribe()
方法取消订阅关系,避免因为使用RxJava而导致的内存溢出。
RxJava订阅过程分析
上面了解到subscribe()
可以传入Observer
对象或是Subscriber
对象,并且都将转换为Subscriber
执行流程。
那我们先看传入Observer
对象的流程。
public final Subscription subscribe(final Observer<? super T> observer) {
if (observer instanceof Subscriber) {
//如果传入的Observer对象是Subscriber的实例,强制转换
return subscribe((Subscriber<? super T>)observer);
}
//新建ObserverSubscriber对象,而这个类是Subscriber的派生类
return subscribe(new ObserverSubscriber<T>(observer));
}
ObserverSubscriber类的源码
public final class ObserverSubscriber<T> extends Subscriber<T> {
final Observer<? super T> observer;
public ObserverSubscriber(Observer<? super T> observer) {
this.observer = observer;
}
@Override
public void onNext(T t) {
observer.onNext(t);
}
@Override
public void onError(Throwable e) {
observer.onError(e);
}
@Override
public void onCompleted() {
observer.onCompleted();
}
}
所以传入Observer
对象都被先转化为Subscriber
对象在使用。最后调用的方法和传入Subscriber
都是一个方法。
//返回的是:Subscription,方便 unsubscribe() 取消订阅,避免内存泄漏
static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
//这是一个可选方法,在发送消息之前
subscriber.onStart();
//将所有的Subscriber实例变成 SafeSubscriber的实例(--观察者)
// 里面error、complete 订阅取消操作,相当于触发这两方法时自动取消订阅
if (!(subscriber instanceof SafeSubscriber)) {
subscriber = new SafeSubscriber<T>(subscriber);
}
try {
//hook.onSubscribeStart方法返回的是 OnSubscribe 实例
//此处call(subscriber)方法的调用的是建立关注事件对象实例时,实现的 Observable.OnSubscribe.call(Subscriber) 方法
//call(Subscriber) 方法将订阅是传入的 Subscriber 传入到 Observable.OnSubscribe.call(Subscriber) 方法中
//OnSubscribe.call(Subscriber) 事件发送逻辑开始运行。
//所以RxJava不是在创建的时候发送消息,而是在订阅之后开始发送消息
hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
return hook.onSubscribeReturn(subscriber);
} catch (Throwable e) {
if (subscriber.isUnsubscribed()) {
//已取消订阅的操作
RxJavaPluginUtils.handleException(hook.onSubscribeError(e));
} else {
// 没有取消订阅,此时subscriber 是 SafeSubscriber 的实例
// subscriber.onError 会调用这个类里面的_onError方法,里面会取消订阅
subscriber.onError(hook.onSubscribeError(e));
}
return Subscriptions.unsubscribed();
}
}
- RxJava 在订阅后开始发送消息
- 关注事件对象实例创建时,创建的
Observable.OnSubscribe.call(Subscriber)
方法里面的 Subscriber 实例,就是Observable.subscribe(Subscriber)
方法传入的实例,用这个实例调用subscriber.onNext("One")
、subscriber.onCompleted()
等方法
熟练使用
Subscription subscribe = observable.subscribe(subscriber);
subscriber 实现了onCompleted()
、onError()
、onNext()
接口。只要传入实现这三个接口对象,可以不用自己去建立个观察者对象的。
Action1<String> nextAction = new Action1<String>() {
@Override
public void call(String s) {
}
};
Action1<Throwable> errorAction = new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
}
};
Action0 completedAction = new Action0() {
@Override
public void call() {
}
};
// 自动创建 Subscriber, 不必传入三个,但定义的方法还是按顺序来
// param1 用来定义onNext(),param2 用来定义 onError(),param3 用来定义 onCompleted()
observable.subscribe(nextAction, errorAction, completedAction);
observable.subscribe(nextAction, errorAction);
observable.subscribe(nextAction);
所以在需要将”One”、”Two”、”There”按顺序Toast打印出来。可以使用如下代码
Observable.just("One", "Two", "There")
//实现生命周期同步,当前组件生命周期结束时自动取消Observable订阅
//避免RxJava导致内存泄漏
.compose(this.<String>bindToLifecycle())
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
ZNotify.toast(mContext, "item:" + s);
}
});
Action0
、Action1
是RxJava提供的接口,还有Action2
、Action3
、ActionX
等。Action0
只有一个call()
无参无返回值方法,刚好 onCompleted()
方法也是无参无返回值的,所以Action0
的call()
取代onCompleted()
的职能。Action1
只有一个call(T t)
一参无返回值方法,和onError()
、onNext()
一样。
看下怎么个替代法
//Observable.subscribe(Action1) 进来的方法
public final Subscription subscribe(final Action1<? super T> onNext) {
//传入的Action1接口对象不能为null
if (onNext == null) {
throw new IllegalArgumentException("onNext can not be null");
}
//获取默认的 onError 、 onCompleted 动作
Action1<Throwable> onError = InternalObservableUtils.ERROR_NOT_IMPLEMENTED;
Action0 onCompleted = Actions.empty();
//ActionSubscriber 是 Subscriber 的派生类
//将这三个动作传入 ActionSubscriber 的构造方法创建其实例(观察者),并用这个实例进行了订阅操作
return subscribe(new ActionSubscriber<T>(onNext, onError, onCompleted));
}
//Observable.subscribe(Action1,Action1)进来
public final Subscription subscribe(final Action1<? super T> onNext, final Action1<Throwable> onError) {
if (onNext == null) {
throw new IllegalArgumentException("onNext can not be null");
}
if (onError == null) {
throw new IllegalArgumentException("onError can not be null");
}
Action0 onCompleted = Actions.empty();
return subscribe(new ActionSubscriber<T>(onNext, onError, onCompleted));
}
//Observable.subscribe(Action1,Action1,Action0)进来
public final Subscription subscribe(final Action1<? super T> onNext, final Action1<Throwable> onError, final Action0 onCompleted) {
if (onNext == null) {
throw new IllegalArgumentException("onNext can not be null");
}
if (onError == null) {
throw new IllegalArgumentException("onError can not be null");
}
if (onCompleted == null) {
throw new IllegalArgumentException("onComplete can not be null");
}
return subscribe(new ActionSubscriber<T>(onNext, onError, onCompleted));
}
RxJava中的变换功能
- 变换:就是将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列。
map()
//将输入的 String 转换为 Bitmap 使用
Observable.just("picture file path")
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String filePath) {
//filePath = "picture file path"
return getBitmap4Path(filePath);
}
})
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) {
//bitmap:从 "picture file path" 图片路径获取的 bitmap 资源
showBitmap(bitmap);
}
});
可见,在map()
方法传入的参数Func1
对象中,将传入的 String 转换为 Bitmap ,并在 Action1
中使用了这个Bitmap。
map()
:直接对事件对象的转换,在RxJava中是最长使用的转换。
FuncX
和ActionX
类似,区别是FuncX
用来包装含有返回值的方法。
Func1<String, Bitmap>
:String 参数,Bitmap是返回值,Func1
表示传入一个参数,Func2
表示传入两个参数,以此类推。返回值只有一个,由最后一个决定返回值类型。如:Func2<String, String, Bitmap>
flatMap()
现在有需求,有多个学生,每个学生有多个课程,现将所有学生的所有课程打印出来。传入的对象是学生,而我们需要对学生的课程进行操作,所以我们决定用map()
转换功能。
Observable.from(students)
.map(new Func1<Student, List<Course>>() {
@Override
public List<Course> call(Student student) {
//进行转换
return student.getCourses();
}
})
.subscribe(new Action1<List<Course>>() {
@Override
public void call(List<Course> courses) {
//遍历
for (Course course : courses) {
Log.d("xxx", course.getCourseName());
}
}
});
虽然实现了要求,但看上去有点怪怪的感觉。这个变换功能是不需要的,不用map()变换反而简单点。
Observable.from(students)
.subscribe(new Action1<Student>() {
@Override
public void call(Student student) {
//遍历
for (Course course : student.getCourses()) {
Log.d("xxx", course.getCourseName());
}
}
});
顿时觉得对于这种要求使用map()
变化,就是脱了裤子放屁。但是不使用变换而用遍历,其实也没必要使用RxJava了,看看使用flatMap()
。
//Observable.from() 会创建一个关注事件对象对象,标记为 firstObservable
Observable.from(students)
.flatMap(new Func1<Student, Observable<Course>>() {
@Override
public Observable<Course> call(Student student) {
//返回泛型为Course的观察者实例,标记为tempObservable
//Observable.from(List)时会依次返回集合中的元素
return Observable.from(student.getCourses());
}
})
.subscribe(new Action1<Course>() {
@Override
public void call(Course course) {
//直接操作 Course 实例
Log.d("xxx", course.getCourseName());
}
});
flatMap()
返回的是关注事件对象对象而subscribe()
操作的是Course实例,这和map()
返回的是List<Course>
操作的也是List<Course>
有区别。
flatMap()
的操作原理:
- 使用传入的事件对象创建一个tempObservable(关注事件对象,看上),这个对象并没有被发送给firstObservable 去通知
subscribe()
(观察者)执行,而是将tempObservable 激活并发送事件 - 创建出来的tempObservable 发出的事件都会被汇入firstObservable ,在由firstObservable通知观察者执行动作
- 然后创建下一个tempObservable 重复操作,直到
onCompleted()
onError()
触发取消订阅
代码例子中的执行逻辑
Observable.from(students)
建立了firstObservablereturn Observable.from(student.getCourses())
建立了tempObservable- tempObservable 发出事件就是依次返回集合中的元素即
Course
对象,没有第三层的Observable
- tempObservable 发出的
Course
对象汇入firstObservable,因为firstObservable是tempObservable 的观察者 - firstObservable收到事件
Course
后发送给它的观察者new Action1<Course>()
(最后会被包装成Subscriber)进行最后的处理
lift() 变换原理 ???????????????
上诉两个变换虽然功能不同,但他们都是针对事件序列的处理和在发送,在内部的都是基于lift(Operator)
变换方法。
简单起见,以单次调用 lift() 的情况分析
Observable
//创建第一个 Observable、OnSubscribe 实例
.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
}
})
//创建第二个 Observable、OnSubscribe 实例
.lift(new Observable.Operator<String, String>() {
@Override
public Subscriber<? super String> call(Subscriber<? super String> subscriber) {
return null;
}
})
//使用第二个 Observable 进行订阅操作,整个RxJava链开始运行
.subscribe(new Subscriber<String>() {
@Override
public void onNext(String s) {
}
...
});
看下 lift()
方法进行的操作
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
return new Observable<R>(new OnSubscribeLift<T, R>(onSubscribe, operator));
}
- 利用 onSubscribe 字段属性创建
OnSubscribeLift
(实现了接口OnSubscribe
)的实例 - onSubscribe 是在构造方法里面赋值,此
lift()
方法是第一个Observable
调用的,所以 onSubscribe是第一个Observable
的字段属性,Observable.create()
传入的值 - 利用
OnSubscribeLift
的实例做参数去创建新的Observable
实例并返回。新建的Observable.onSubscribe
属性就是此OnSubscribeLift
实例,当前lift()
建立的Observable
实例 调用lift()
时使用
看看 OnSubscribeLift
类,省略了些容错判断
public final class OnSubscribeLift<T, R> implements OnSubscribe<R> {
static final RxJavaObservableExecutionHook hook = RxJavaPlugins.getInstance().getObservableExecutionHook();
// 上(旧)一级 的Observable 的 OnSubscribe 的引用,可以触发上一级 OnSubscribe 的 call() 方法
final OnSubscribe<T> parent;
final Operator<? extends R, ? super T> operator;
//parent:调用 lift() 方法的 Observable 的 onSubscribe 字段, 上(旧)一级 的Observable
//operator:Observable.Operator实例,是 Func1 的派生类,lift() 方法调用是需要传入并实现其 call() 方法。
public OnSubscribeLift(OnSubscribe<T> parent, Operator<? extends R, ? super T> operator) {
this.parent = parent;
this.operator = operator;
}
//下(新)一级 Observable 有本(老一)级的 Observable 的 OnSubscribe 的引用,调用这个引用的 call() 方法触发
public void call(Subscriber<? super R> o) {
try {
//利用 下(新)一级 传入的 Subscriber 实例
//经过 lift() 方法传入实例实现的 Observable.Operator.call() 方法
//获取到新的 Subscriber 实例
Subscriber<? super T> st = hook.onLift(operator).call(o);
st.onStart();
//将获取的新的 Subscriber 实例,传入到 上(旧)一级
//parent: 上(旧)一级 的Observable 的字段属性
parent.call(st);
}
}
}
- 除开构造方法,就一个
call(Subscriber)
方法,用来实现借口方法OnSubscribe.call(Subscriber)
- 这个方法里面建立了新的
Subscriber
实例,并此实例作为参数触发创建上一个Observable
时实现的Observable.OnSubscribe.call(Subscriber)
方法 call()
调用对象和时间: 在这个实例情况相爱,lift()
之后执行了subscribe()
,就是用新的Observable
实例进行了订阅方法,前面了解到订阅方法subscribe()
会自动触发进行订阅操作的Observable
的onSubscribe
字段的call()
方法。
在这个简单情况下的总结分析
- 有两个
Observable
- 有两个
OnSubscribe
- 订阅方法
subscribe()
是新的Observable
实例调用,触发的 OnSubscribe 是创建新的 Observable 时新建的OnSubscribe
(lift()
时建立的) - 新的
OnSubscribe.call()
方法中,会创建新的Subscriber
实例,以此为参触发 老的OnSubscribe.call()
(创建第一个Observable
时建立的)方法,相当于进行订阅操作
Scheduler 线程控制器
Scheduler认识
Scheduler用来控制代码运行所在线程的东西,RxJava内置了几个Scheduler
Schedulers.immediate()
:直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。Schedulers.newThread()
:总是启用新线程,并在新线程执行操作。Schedulers.io()
:I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。Schedulers.computation()
:计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。AndroidSchedulers.mainThread()
:它指定的操作将在 Android 主线程运行。需要导入:compile 'io.reactivex:rxandroid:1.2.0'
Scheduler使用
Observable
.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
//可能进行计算、I/O、网络请求等才做
}
})
// 指定subscribe()发生的线程。 根据操作选择合适的线程
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
//运行在新线程,由 observeOn() 指定
.map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
//A操作,需新线程
return null;
}
})
.observeOn(Schedulers.computation())
//运行在计算线程,由 observeOn() 指定
.map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
//B操作,需计算线程
return null;
}
})
.observeOn(AndroidSchedulers.mainThread())
// 指定 Subscriber(观察者) 的回调发生在主线程
.subscribe(new Action1<String>() {
@Override
public void call(String number) {
//C操作,需主线程
}
});
上面代码借助Scheduler我们进行了线程的多次切换,由subscribeOn()
和observeOn()
方法设置。
Scheduler原理
要先知道,一条RxJava操作链有多个Observable
,因为在调用create()
、map()
、subscribeOn()
、subscribe()
等方法时,都会返回一个新的 Observable
对象。
原理分析:
subscribeOn()
- 发生在
OnSubscribe
中,在事件开始发送之前。 - 从事件发出的开端就造成影响,直到发生进行的切换,即调用
observeOn()
- 与
observeOn()
不同,只能调用一次,无调用位置要求。
- 发生在
observeOn()
- 发生在
observeOn()
内建的Subscriber
中。在它即将给下一级Subscriber
发送事件时 - 影响以后将创建的
Subscriber
,控制的是后面的线程。 - 如上:A操作需要在新线程中运行,在A操作进行前使用
observeOn()
调整线程,同样在B、C操作之前调整线程。
- 发生在
看图分析
图中共有 5 处含有对事件的操作。
- ①和②:受 subscribeOn() 影响
- ③和④:受第一个 observeOn() 的影响
- ⑤:受第二个 onserveOn() 影响
第二次调用 subscribeOn()
(黄色线段),在通知过程中,线程就被第一个 subscribeOn()
(红色线段) 截断,因此对整个流程并没有任何影响。
所以多次调用 subscribeOn()
方法,只有第一个能起作用。
RxJava方便快发的小功能
依赖库的导入
//RxJava 依赖库
compile 'io.reactivex:rxjava:1.1.5'
//生命周期和取消订阅控制,解决有RxJava导致的内存泄漏
compile 'com.trello:rxlifecycle:0.4.0'
compile 'com.trello:rxlifecycle-components:0.4.0'
//RxAndroid唯一用处,就是AndroidSchedulers.mainThread在主线程中运行
compile 'io.reactivex:rxandroid:1.2.0'
//用RxJava实现Android中的SharedPreferences
compile 'com.f2prateek.rx.preferences:rx-preferences:1.0.1'
View防抖动点击
RxView.clicks(btnClick)//触发事件的View
.throttleFirst(3, TimeUnit.SECONDS)//时间数值、单位
.compose(this.<Void>bindToLifecycle())
//订阅的事件
.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
ZNotify.toast(getMContext(), "this is a message");
}
});
CheckBox状态实时更新
RxCompoundButton.checkedChanges(checkBox)//绑定 CheckBox 控件
.compose(this.<Boolean>bindToLifecycle())
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
//CheckBox 发生改变后的动作
btnLogin.setClickable(aBoolean);
}
});
模拟搜索关键字提醒功能
RxTextView.textChangeEvents(etSearch)
//每次输入完之后又500毫秒的缓冲时间,默认在computation调度器
.debounce(500, TimeUnit.MILLISECONDS)
//指定事件消费线程,这里是主线程
.observeOn(AndroidSchedulers.mainThread())
.compose(this.<TextViewTextChangeEvent>bindToLifecycle())
//观察者收到信息开始处理,此处代表着text文本改变的信息
.subscribe(new Action1<TextViewTextChangeEvent>() {
@Override
public void call(TextViewTextChangeEvent textViewTextChangeEvent) {
//做你想做的
}
});
Buffer操作符
点击三次按钮发送一次数据
RxView.clicks(btnBufferCount)//
.compose(this.<Void>bindToLifecycle())
.buffer(3)//点击次数
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<Void>>() {
@Override
public void call(List<Void> voids) {
ZNotify.toast(getMContext(), getString(R.string.hint_buffer_count));
}
});
对于数据源:{1, 2, 3, 4, 5, 6, 7, 8, 9}
两两打包发送并跳过第三项:{1, 2}、{4, 5}、{7, 8}
Character[] chs = {1, 2, 3, 4, 5, 6, 7, 8, 9};
Observable.from(chs)//设置数据源
//每组取两个,第二组从第3个以后开始取(不包含第3个)
.buffer(2, 3)
.compose(this.<List<Character>>bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<Character>>() {
@Override
public void call(List<Character> characters) {
//“每组”都调用一次这个方法,做你想做的
}
});
zip数据合并
Observable
//模拟读取本地和网络数据,最终将数据合并显示(必须等最慢的获取到数据)
.zip(query4Location(), query4Net(), new Func2<List<ContacterBean>, List<ContacterBean>, List<ContacterBean>>() {
@Override
public List<ContacterBean> call(List<ContacterBean> contacterBeen, List<ContacterBean> contacterBeen2) {
contacterBeen.addAll(contacterBeen2);
return contacterBeen;
}
}).compose(this.<List<ContacterBean>>bindToLifecycle())
//指定事件发生线程,耗时操作一般放到io线程,比如网络请求的
.subscribeOn(Schedulers.io())
//指定事件消费线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<ContacterBean>>() {
@Override
public void call(List<ContacterBean> contacterBeen) {
//网络数据和本地数据以组合完成
}
});
megre数据合并
//模拟网络请求中,先显示本地数据,网络数据加载完成后显示网络数据
Observable.merge(query4Location(), query4Net())
.compose(this.<List<ContacterBean>>bindToLifecycle())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<ContacterBean>>() {
@Override
public void call(List<ContacterBean> contacterBeen) {
showPage(contacterBeen);
}
});
轮训器
//延时3000 ,每间隔3000,时间单位
Observable.interval(3000, 3000, TimeUnit.MILLISECONDS)
//实现生命周期同步,当前组件生命周期结束时自动取消Observable订阅
.compose(this.<Long>bindToLifecycle())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
//做你想做的
}
});
定时器
//定时三秒执行
Observable.timer(3000, TimeUnit.MILLISECONDS)
.compose(this.<Long>bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
//做你想做的
}
});
可连接的SUBJECT
1.建立一个全局的公共变量publishSubject
public static PublishSubject<String> publishSubject = PublishSubject.create();
2.在一个界面使用两个FrameLayout并显示不同的Fragment对象
TopFragment topFrag = TopFragment.newInstance();
BottomFragment bottomFrag = BottomFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.fl_top, topFrag, "top")
.replace(R.id.fl_bottom, bottomFrag, "bottom")
.commit();
3.TopFragment使用全局公共变量publishSubject的onNext()方法发送信息。
RxPublishSubjectFrag.publishSubject.onNext("message");
4.BottomFragment使用全局公共变量publishSubject订阅事件,获取到TopFragment发送的信息
RxPublishSubjectFrag.publishSubject.subscribe(new Action1<String>() {
@Override
public void call(String s) {
tvResult.setText(s);
}
});
RxBus
PublishSubject线程不安全,Subject<Object, Object>是线程安全的。在RxBus中选择使用线程安全的方式。
1.在Activity中建立rxBus自定义类的对象和获取方法
private RxBus rxBus;
public RxBus getRxBusSingleton() {
if (rxBus == null)
rxBus = new RxBus();
return rxBus;
}
2.在发送事件消息的Fragment中使用rxBus对象发送事件消息(RxEvent对象)
rxBus.send(new RxBus.RxEvent(0, "message"));
3.在接收事件消息的Fragment中使用rxBus对象
- 将普通的 Observable 转换为可连接的 Observable
ConnectableObservable<RxEvent> tapEventEmitter = rxBus.toObserverable().publish();
- 使用ConnectableObservable对象去订阅事件,获取到RxEvent事件消息
事件发出后立即接受
tapEventEmitter.compose(this.<RxEvent>bindToLifecycle())
.subscribe(new Action1<RxEvent>() {
@Override
public void call(RxEvent event) {
if (event.eventKey == 0)
_showTapText();
}
});
设置一段缓冲时间,在这段缓冲时间内事件发出后不会立马消费,就是说不会立即回调订阅的Action动作消费事件。
tapEventEmitter
//在指定的生命周期方法调用时取消订阅
.compose(this.<RxEvent>bindUntilEvent(FragmentEvent.DESTROY))
.publish(new Func1<Observable<RxEvent>, Observable<List<RxEvent>>>() {
@Override
public Observable<List<RxEvent>> call(Observable<RxEvent> stream) {
//设置 1s 的缓冲时间,在这段时间内收到的消息全部放入缓存,等缓冲时间结束后统一发送
return stream.buffer(stream.debounce(1, TimeUnit.SECONDS));
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<RxEvent>>() {
@Override
public void call(List<RxEvent> events) {
//收到缓冲时间内所有的event事件
int size = events.size();
RxEvent event = events.get(0);
if (event.eventKey == 0)
_showTapCount((String) event.eventValue + size);
}
});
- 可连接的Observable并不在订阅时触发,而需手动调用connect()方法
tapEventEmitter.connect();
RxBus 类
public class RxBus {
private final Subject<RxEvent, RxEvent> _busSubject;
public RxBus() {
PublishSubject<RxEvent> objectPublishSubject = PublishSubject.create();
_busSubject = new SerializedSubject<>(objectPublishSubject);
}
public void send(RxEvent event) {
_busSubject.onNext(event);
}
public Observable<RxEvent> toObserverable() {
return _busSubject;
}
public boolean hasObservers() {
return _busSubject.hasObservers();
}
public static class RxEvent {
public int eventKey;
public Object eventValue;
public RxEvent(int eventKey, Object eventValue) {
this.eventKey = eventKey;
this.eventValue = eventValue;
}
}
}
以下功能在项目里面有包含:
- RxJava + OkHttp + GSON 构建请求
- RxJava + Retrofit的使用
项目地址:里面有APP长用到的东西,RxJava的使用里面也有。