rxjava之复习
二.rxjava介绍
一. Rxjava的基本及其使用介绍:
1.rxjava是什么
2.原理和介绍
3.线程切换
Github
https://github.com/ReactiveX/RxJava
https://github.com/ReactiveX/RxAndroid
compile 'io.reactivex:rxjava:1.0.14'
compile 'io.reactivex:rxandroid:1.0.1'
一.RxJava是什么
RxJava是一个在Java VM 上使用可观测的序列,来组成异步的、基于事件的程序的库。本质上是一个实现异步操作的库
优势:在程序逻辑变得越来越复杂时,可以保持程序的简洁。
1.1 API 介绍和原理
1. 观察者模式
RxJava 异步实现,是通过一种扩展的观察者模式来实现的。
观察者设计模式: 对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖它的对象都得到通知并自动刷新。
RxJava 的观察者模式
RxJava 有四个基本概念:Observable (被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。被观察者和观察者通过 subscribe()方法实现订阅关系,从而被观察者可以在需要的时候发出事件来通知观察者。
RxJava事件回调方法 onNext()、onCompleted() 和 onError()。
- onNext():RxJava把每个事件单独处理,当一个事件队列完成后,会调用onNext()方法。
- onCompleted(): 事件队列结束,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为完成标志。
- onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
注意:onCompleted() 和 onError() 是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
2.基本实现
基本实现完整代码:
//写法1:被观察者 Observable observable = Observable.create(new Observable.OnSubscribe<String>(){ @Override public void call(Subscriber<? super String> subscriber){ subscriber.onNext("Hello"); subscriber.onNext("Rxjava"); subscriber.onNext("RxAndroid"); subscriber.onCompleted(); }}); // 写法2: 被观察者 Subscriber<String> subscriber = new Subscriber<String>(){ @Override public void onCompleted(){} @Override public void onError(Throwable e){} @Override public void onNext(String s){}}; //写法3: Observable observable = Observable.just("Hello","Rxjava","RxAndroid"); //String[] strings = {"Hello","Rxjava","RxAndroid"}; //Observable observable = Observable.from(strings); //被观察者订阅观察者 observable.subscribe(observer); //观察者Observer Observer<String> observer = new Observer<String>(){ @Override public void onNext(String s) {} @Override public void onCompleted() {} @Override public void onError(Throwable e) {}}; observable.subscribe(observer 或 subscriber); //被观察者订阅观察者 执行结果: 01-16 13:35:02.734 12509-12509/com.zhoujian.rxjava I/MainActivity: onNext方法执行了: Hello 01-16 13:35:02.734 12509-12509/com.zhoujian.rxjava I/MainActivity: onNext方法执行了: Rxjava 01-16 13:35:02.734 12509-12509/com.zhoujian.rxjava I/MainActivity: onNext方法执行了: RxAndroid 01-16 13:35:02.734 12509-12509/com.zhoujian.rxjava I/MainActivity: Completed方法执行了
基本实现主要有三点:
1)创建 Observer(观察者):
Subscriber(抽象类):使用方式同Observer,RxJava还内置一个实现Observer的Subscriber(抽象类), 对Observer接口进行一些扩展。
Observer<String> observer = new Observer<String>(){
@Override
public void onNext(String s) {}
@Override
public void onCompleted() {}
@Override
public void onError(Throwable e) {}};
Subscriber<String> subscriber = new Subscriber<String>(){
@Override
public void onCompleted(){ }
@Override
public void onError(Throwable e){}
@Override
public void onNext(String s){}};
两者使用方式是一样的,实质上,在 RxJava 的subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber 再使用,区别主要有两点:
第一:onStart(),这是 Subscriber 增加方法。它会在subscribe刚开始,而事件还未发送之前被调用,可以用于做一些准备工作。例如数据的清零或重置。它总是在 subscribe 所发生的线程被调用,而不能指定线程。要在指定的线程来做准备工作,可以使用 doOnSubscribe() 方法。
第二:unsubscribe(),是Subscriber实现的另一个接口Subscription 的方法,用于取消订阅。
在这个方法被调用后,Subscriber 将不再接收事件。一般在这个方法调用前,可以使用 isUnsubscribed()先判断一下状态,可以在onPause() onStop() 等方法中调用 unsubscribe() 来解除引用关系,以避免内存泄露的发生。
2)创建Observable(被观察者)
11)create() 最基本的创造事件序列。
Observable observable = Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber)
{subscriber.onNext("Hello");}});
12)just(T...): 将传入的参数依次发送出来:
Observable observable = Observable.just("Hello", "Rxjava", "RxAndroid");
13)from(T[]) / from(Iterable<? extends T>) : 将传入的数组或 Iterable 拆分成具体对象后,依次发送出来。
String[] strings = {"Hello", "Rxjava", "RxAndroid"};
Observable observable = Observable.from(strings);
OnSubscribe 会被存储在返回的Observable 对象中,它的作用相当于一个计划表。当Observable被订阅的时候,OnSubscribe 的call() 自动被调用,事件序列就会依照设定依次触发。
Observable observable = Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber){
subscriber.onNext("Hello");
subscriber.onNext("Rxjava");
subscriber.onNext("RxAndroid");
subscriber.onCompleted();
}});
3) Subscribe (订阅)
observable.subscribe(observer 或 subscriber);
4) 自定义回调
注意: Action1 和Action0 是 RxJava 的接口,Action1表示有一个返回值,Action0表示没有返回值。
被观察者(Observable):
Observable observable = Observable.just("Hello","Rxjava","RxAndroid");
自定义回调的观察者:
//自定义回调
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 completeAction = new Action0() {
@Override
public void call() {}};
//observable.subscribe(nextAction);
//observable.subscribe(nextAction,errorAction);
observable.subscribe(nextAction,errorAction,completeAction);
执行结果:
01-16 13:50:26.964 12509-12509/com.zhoujian.rxjava I/MainActivity: 自定义回调----onNext方法执行了: Hello
01-16 13:50:26.964 12509-12509/com.zhoujian.rxjava I/MainActivity: 自定义回调----onNext方法执行了: Rxjava
01-16 13:50:26.964 12509-12509/com.zhoujian.rxjava I/MainActivity: 自定义回调----onNext方法执行了: RxAndroid
01-16 13:50:26.964 12509-12509/com.zhoujian.rxjava I/MainActivity: 自定义回调----Completed方法执行了
举个例子a:打印数组中的元素
String[] names = {"周杰伦","周星驰","周润发"};
//利用自定义回调
Observable.from(names).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, "姓名:=="+s);}});
执行结果:
01-16 13:55:42.937 12509-12509/com.zhoujian.rxjava I/MainActivity: 姓名:==周杰伦
01-16 13:55:42.937 12509-12509/com.zhoujian.rxjava I/MainActivity: 姓名:==周星驰
01-16 13:55:42.937 12509-12509/com.zhoujian.rxjava I/MainActivity: 姓名:==周润发
举例b:加载显示图片
Observable observable = Observable.create(new Observable.OnSubscribe<Drawable>() {
@Override
public void call(Subscriber<? super Drawable> subscriber) {
Drawable drawable = getResources().getDrawable(R.mipmap.my);
subscriber.onNext(drawable);
subscriber.onCompleted();
}});
Observer<Drawable> observer= new Observer<Drawable>() {
@Override
public void onCompleted() {
Log.d(TAG, "onCompleted方法执行了");
}
@Override
public void onError(Throwable e) {}
@Override
public void onNext(Drawable drawable) {
Log.d(TAG, "onNext方法执行了");
img.setImageDrawable(drawable);
Log.d(TAG, "图片加载完成了!");}};
observable.subscribe(observer);
执行结果:
01-16 14:09:06.752 10355-10355/com.zhoujian.rxjava D/MainActivity: onNext方法执行了
01-16 14:09:06.752 10355-10355/com.zhoujian.rxjava D/MainActivity: 图片加载完成了!
01-16 14:09:06.753 10355-10355/com.zhoujian.rxjava D/MainActivity: onCompleted方法执行了
3. Scheduler(线程控制)
在不指定线程的情况下, RxJava 遵循是线程不变的原则,
即:在哪个线程调用 subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,用到Scheduler。
用subscribeOn() 和 observeOn() 对线程进行控制。
subscribeOn(): 指定事件产生所在线程。 observeOn(): 指定事件消费所在线程。
- Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程。 这是默认的 Scheduler。
- Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
- Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。
- Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算
- Android专用AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。
以加载显示图片例子说明:
Observable.create(new Observable.OnSubscribe<Drawable>() { @Override public void call(Subscriber<? super Drawable> subscriber) { Drawable drawable = getResources().getDrawable(R.mipmap.my); subscriber.onNext(drawable); subscriber.onCompleted();}}) .subscribeOn(Schedulers.io())//上面的call方法发生在io线程 . observeOn(AndroidSchedulers.mainThread())//下面显示图片发生在主线程 . subscribe(new Observer<Drawable>() { @Override public void onCompleted() { Log.d(TAG, "onCompleted方法执行了");} @Override public void onError(Throwable e) {}; @Override public void onNext(Drawable drawable) { Log.d(TAG, "onNext方法执行了"); img.setImageDrawable(drawable); Log.d(TAG, "图片加载完成了!");}});
4. 变换: 就是将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列。
- 变换之map(): 一对一的转换(常见的变换)
map() 将参数中String对象转换成Integer对象后返回,而在经过map()后,事件的参数类型也由String转为integer。
例a:把String类型转换成Integer
Observable.just("100")
.map(new Func1<String, Integer>(){
@Override
public Integer call(String s){
return Integer.valueOf(s);}})
.subscribe(new Action1<Integer>(){
@Override
public void call(Integer integer){
Log.d(TAG, "String转成Integer完成,integer的值为:"+integer.intValue());
}});
Func1 和 Action1非常相似,也是 RxJava一个接口,用于包装含有一个参数的方法。 Func1 和 Action区别, Func1包装是有返回值方法。
另外,和 ActionX 一样, FuncX 也有多个,用于不同参数个数的方法。FuncX和 ActionX区别在 FuncX 包装的是有返回值的方法。
例子b:把JavaBean对象转换成String类型输出
/ 再封装一个电影Movie的JavaBean,一个电影中有多个演员 public class Movie{ private String name; private int id; private String data; private List<Actor> mactorList; public Movie(String data, int id, List<Actor> mactorList, String name){} @Override public String toString() { return "Movie{" + "data='" + data + '\'' + ", name='" + name + '\'' +", id=" + id + ", mactorList=" + mactorList + '}';}}
Observable observable = Observable.from(movies).map(new Func1<Movie, String>() { @Override public String call(Movie movie) { return movie.toString(); }}); Observer observer = new Observer<String>() { @Override public void onCompleted() { Log.i(TAG, "Completed方法执行了"); } @Override public void onNext(String s) { Log.i(TAG, "onNext方法执行了"); Log.i(TAG,"s==="+s); }}; observable.subscribe(observer); 01-16 15:34:20.291 31780-31780/com.zhoujian.rxjava I/MainActivity: onNext方法执行了 01-16 15:34:20.291 31780-31780/com.zhoujian.rxjava I/MainActivity: s===Movie{data='1998-10-14', name='喜剧之王',
id=1, mactorList=[Actor{name='周星驰', sex='男'}, Actor{name='张柏芝', sex='女'}]} 01-16 15:34:20.291 31780-31780/com.zhoujian.rxjava I/MainActivity: onNext方法执行了 01-16 15:34:20.291 31780-31780/com.zhoujian.rxjava I/MainActivity: s===Movie{data='2016-05-01', name='美人鱼',
id=2, mactorList=[Actor{name='罗志祥', sex='男'}, Actor{name='张雨绮', sex='女'}]} 01-16 15:34:20.291 31780-31780/com.zhoujian.rxjava I/MainActivity: Completed方法执行了
- 变换之flatMap():一对多的转换
还是上述电影例子,如把一个电影转换成多个演员输出,要用到flatMap(),一对多的转换。
从上面的代码可以看出, flatMap() 和 map() 有一个相同点:它也是把传入的参数转化之后返回另一个对象。 flatMap() 返回的是个Observable对象,并且这个Observable 对象并不是被直接发送到了 Subscriber的回调方法中。
flatMap() 的原理:
第一,使用传入的事件对象创建一个 Observable 对象。
第二, 并不发送这个 Observable, 而是将它激活,于是它开始发送事件。
第三,每一个创建出来的Observable发送的事件,都被汇入同一个 Observable ,而这个Observable负责将这些事件统一交给Subscriber的回调方法。
Observer<Actor> observer = new Observer<Actor>() { @Override public void onNext(Actor actor) { Log.i(TAG, "onNext方法执行了"); Log.i(TAG, "actor===" + actor.toString()); } }; Observable.from(movies).flatMap(new Func1<Movie, Observable<Actor>>() { @Override public Observable<Actor> call(Movie movie) { return Observable.from(movie.getMactorList()); }}).subscribe(observer); 执行结果: 01-16 15:44:18.897 31780-31780/com.zhoujian.rxjava I/MainActivity: onNext方法执行了 01-16 15:44:18.897 31780-31780/com.zhoujian.rxjava I/MainActivity: actor===Actor{name='周星驰', sex='男'} 01-16 15:44:18.897 31780-31780/com.zhoujian.rxjava I/MainActivity: onNext方法执行了 01-16 15:44:18.897 31780-31780/com.zhoujian.rxjava I/MainActivity: actor===Actor{name='张柏芝', sex='女'} 01-16 15:44:18.897 31780-31780/com.zhoujian.rxjava I/MainActivity: onNext方法执行了 01-16 15:44:18.897 31780-31780/com.zhoujian.rxjava I/MainActivity: actor===Actor{name='罗志祥', sex='男'} 01-16 15:44:18.897 31780-31780/com.zhoujian.rxjava I/MainActivity: onNext方法执行了 01-16 15:44:18.897 31780-31780/com.zhoujian.rxjava I/MainActivity: actor===Actor{name='张雨绮', sex='女'} 01-16 15:44:18.897 31780-31780/com.zhoujian.rxjava I/MainActivity: Completed方法执行了
1.1 变换的原理:
lift() :
这些变换虽功能不同,但实质上都是针对事件序列的处理和再发送。而在 RxJava 的内部,它们是基于同一个基础的变换方法: lift(Operator)
Observable执行lift(Operator) 后,会返回一个新的Observable,它会像一个代理一样,负责接收原始的Observable 发出的事件,并在处理后发送给 Subscriber。像一种代理机制,通过事件拦截和处理实现事件序列的变换。
public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
return Observable.create(new OnSubscribe<R>() {
@Override
public void call(Subscriber subscriber) {
Subscriber newSubscriber = operator.call(subscriber);
newSubscriber.onStart();
onSubscribe.call(newSubscriber);
}});}
compose对Observable整体的变换:
除了 lift() 之外, Observable还有一个变换方法叫做 compose(Transformer)。
和lift()区别在于, lift()是针对事件项和事件序列的,而 compose()是针对Observable自身进行变换。
public class LiftTransformer implements Observable.Transformer<Integer, String> {
@Override
public Observable<String> call(Observable<Integer> observable) {
return observable
.lift1() .lift2().lift3() }}
...
Transformer liftAll = new LiftTransformer();
observable1.compose(liftAll).subscribe(subscriber1);
observable2.compose(liftAll).subscribe(subscriber2);
observable3.compose(liftAll).subscribe(subscriber3);
还是原来的例子,String转Integer
Observable.just("100") //主线程中执行,由subscribeOn指定
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(Schedulers.io())
.map(new Func1<String, Integer>(){// IO 线程,由observeOn()指定
@Override
public Integer call(String s){
return Integer.valueOf(s);}})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Integer>() {// Android 主线程,由 observeOn() 指定
@Override
public void call(Integer integer){
Log.d(TAG, "String转换成Integer完成了,integer的值为:"+integer.intValue());
}});
一. Rxjava的基本及其使用介绍:
收藏的 扔物线 大神写的RxJava入门文章看了。
http://gank.io/post/560e15be2dca930e00da1083
花了一晚上看完,顺便做做笔记,然后试着把上传和压缩图片的逻辑改用RxJava实现。
发现真的用得很爽。不需要在Handler中跳来跳去,还自带线程调度,真棒。
下面是乱写的笔记,有些是直接Ctrl+C,Ctrl+V的,记得乱七八糟,估计也就我自己清楚这笔记写的是什么鬼了(其实就是就为了水篇博客而已,手动滑稽)。
下载
https://github.com/ReactiveX/RxJava
https://github.com/ReactiveX/RxAndroid
写笔记时的最新版:compile 'io.reactivex:rxjava:1.0.14'
compile 'io.reactivex:rxandroid:1.0.1'
理解
RxJava主要用到观察者模式,观察者
和被观察者
通过订阅
完成绑定。
在程序中,观察者
无法或者不好去主动(即定时查询,这样比较浪费性能,而且不及时)去获取被观察者
的状态。
一般是在被观察者
发生事件时,再去通知观察者
。虽然这和现实的情况有点区别。
用法:
流程
->实现被观察者
,绑定事件
—>实现观察者
,定义事件的响应
—->观察者订阅
事件(被观察者
.subscribe(观察者
))
——>被订阅者开始发送事件
API
Observable
:被观察者
通过create()
、just()
、from()
来绑定(输入)事件来构造被观察者
对象
通过subscribe()
跟观察者
并联,并开始向观察者
发送事件
通过map()
,将输入的事件进行转换(加工)成另一个事件,返回结果给观察者响应
flatMap()
,可以
将输入的事件进行转换(加工)成其他事件(1转1
,或者1转多
),将新事件绑定到新的被观察者
,构成新的被观察者
对象,返回此新被观察者
对象
(之后会由新被观察者
发事件给观察者
,所以subscribe()
的时候,需要注意观察者
响应的是事件类型,要跟新观察者
一致)
lift()
对目标订阅者
进行层层包装,通过Observable.Operator
,让包装后的订阅者
可以直接处理事件
。compose()
是对多个lift()
的封装
throttleFirst()
在每次事件触发后的一定时间间隔内丢弃新的事件,用作防抖什么的,按一次后,多少时间内再按了也没用
Observer
:观察者
主要响应事件onNext()
、onCompleted()
和onError()
onCompleted()
和onError()
互斥
Subscriber
:实现了Observer
的抽象类
onStart()
: 这是 Subscriber 增加的方法。它会在 subscribe 刚开始,而事件还未发送之前被调用,可以用于做一些准备工作,- 例如数据的清零或重置。这是一个可选方法,默认情况下它的实现为空。
- 需要注意的是,如果对准备工作的线程有要求(例如弹出一个显示进度的对话框,这必须在主线程执行), onStart() 就不适用了,因为它总是在 subscribe 所发生的线程被调用,而不能指定线程。要在指定的线程来做准备工作,可以使用 doOnSubscribe() 方法,具体可以在后面的文中看到。
unsubscribe()
: 这是 Subscriber 所实现的另一个接口 Subscription 的方法,用于取消订阅。- 在这个方法被调用后,Subscriber 将不再接收事件。一般在这个方法调用前,可以使用 isUnsubscribed() 先判断一下状态。
- unsubscribe() 这个方法很重要,因为在 subscribe() 之后, Observable 会持有 Subscriber 的引用,这个引用如果不能及时被释放,将有内存泄露的风险。所以最好保持一个原则:要在不再使用的时候尽快在合适的地方(例如 onPause() onStop() 等方法中)调用 unsubscribe() 来解除引用关系,以避免内存泄露的发生。
Action0
、Action1
和ActionX
:Observer
的不完整版
Action0
只响应一个事件,对应onCompleted()
Action1
只响应一个事件,对应onNext()
和onCompleted()
,还有其他Action2
、Action3
等
Observable.OnSubscribe
:订阅
其实就是事件
的抽象,事件
会激发观察者
,即调用观察者
的响应回调
Scheduler:线程控制
Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.map(mapOperator) // 新线程,由 observeOn() 指定
.observeOn(Schedulers.io())
.map(mapOperator2) // IO 线程,由 observeOn() 指定
.observeOn(AndroidSchedulers.mainThread)
.subscribe(subscriber); // Android 主线程,由 observeOn() 指定
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 主线程运行。
subscribeOn()
指定 订阅事件发生的线程(只生效一次,最先调用那次)observeOn()
指定 观察者响应的线程,可调用(生效)多次doOnSubscribe()
doOnSubscribe()的后面跟一个 subscribeOn() ,就能指定准备工作的线程了。
doOnSubscribe()
和Subscriber.onStart()
同样是在 subscribe() 调用后而且在事件发送前执行,但区别在于它可以指定线程。
默认情况下, doOnSubscribe() 执行在 subscribe() 发生的线程;而如果在 doOnSubscribe() 之后有 subscribeOn() 的话,它将执行在离它最近的 subscribeOn() 所指定的线程。
Observable.create(onSubscribe)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Action0() {
@Override
public void call() {
progressBar.setVisibility(View.VISIBLE); // 需要在主线程执行
}
})
.subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
1.1 Rxjava的基本及其使用介绍:
RxJava的异步实现正是基于观察者模式来实现的,而且是一种扩展的观察者模式。
1.观察者模式概念?
观察者模式基于Subject这个概念,Subject是一种特殊对象,又叫做主题或者被观察者。当它改变时那些由它保存的一系列对象将会得到通知,而这一系列对象被称作Observer(观察者)。它们会对外暴漏了一个通知方法(比方说update之类的),当Subject状态发生变化时会调用的这个方法。
观察者模式很适合下面这些场景中的任何一个:
当你的架构有两个实体类,一个依赖另一个,你想让它们互不影响或者是独立复用它们时。
当一个变化的对象通知那些与它自身变化相关联的未知数量的对象时。
当一个变化的对象通知那些无需推断具体类型的对象时。
在RxJava中主要有4个角色:
Observable(被观察者)
Subject
Observer(观察者)
Subscriber(观察者:其实是一个实现了Observer的抽象类)
Observable和Subject是两个“生产”实体,Observer和Subscriber是两个“消费”实体。说直白点Observable对应于观察者模式中的被观察者,而Observer和Subscriber对应于观察者模式中的观察者。
后面我们分析源码的时候也会介绍到。Subject比较复杂,以后再分析。
上一篇文章中我们说到RxJava中有个关键概念:事件。观察者Observer和被观察者Observable通过subscribe()方法实现订阅关系。从而Observable可以在需要的时候发出事件来通知Observer。
1.2.RxJava如何使用?
第一步:创建观察者Observer
Observer<Object> observer = new Observer<Object>() {
@Override
public void onCompleted() {}};
在普通的观察者模式中观察者一般只会提供一个update()方法用于被观察者的状态发生变化时,用于提供给被观察者调用。开篇我们讲过RxJava是基于一种扩展的观察这模式实现,这里多出的onCompleted和onError正是对观察者模式的扩展。
ps:onNext就相当于普通观察者模式中的update
RxJava中添加了普通观察者模式缺失的三个功能:
第二步:创建被观察者Observable
Observable.create()方法可以创建一个Observable,使用crate()创建Observable需要一个OnSubscribe对象,这个对象继承Action1。当观察者订阅我们的Observable时,它作为一个参数传入并执行call()函数。
Observable<Object> observable = Observable.create(new Observable.OnSubscribe<Object>() {
@Override
public void call(Subscriber<? super Object> subscriber) {}});
除了create(),just()和from()同样可以创建Observable。
看看下面两个例子:just(T...)将传入的参数依次发送
Observable observable = Observable.just("One", "Two", "Three");
//上面这行代码会依次调用
//onNext("One");
//onNext("Two");
//onNext("Three");
//onCompleted();
from(T[])/from(Iterable<? extends T>)将传入的数组或者Iterable拆分成Java对象依次发送
String[] parameters = {"One", "Two", "Three"};
Observable observable = Observable.from(parameters);
//上面这行代码会依次调用
//onNext("One");
//onNext("Two");
//onNext("Three");
//onCompleted();
第三步:被观察者Observable订阅观察者Observer(ps:你没看错,不同于普通的观察者模式,这里是被观察者订阅观察者)
有了观察者和被观察者,我们就可以通过subscribe()l,来实现二者的订阅关系了。
observable.subscribe(observer);
连在一起写就是这样:
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for (int i = 0; i < 5; i++) {
subscriber.onNext(i);}
subscriber.onCompleted();}
}).subscribe(new Observer<Integer>() {
@Override
public void onCompleted() {
System.out.println("onCompleted");
}});至此一个完整的RxJava调用就完成了。
兄台,可是我没搞定你特么到底在干啥啊?不急,我现在就来告诉你们到底发生了什么。
首先我们使用Observable.create()创建了一个新的Observable<Integer>,并为create()方法传入了一个OnSubscribe,OnSubscribe中包含一个call()方法,一旦我们调用subscribe()订阅后就会自动触发call()方法。
call()方法中的参数Subscriber其实就是subscribe()方法中的观察者Observer。
我们在call()方法中调用了5次onNext()和1次onCompleted()方法。一套流程周下来以后输出结果就是下面这样的:
Item is 0
Item is 1
Item is 2
Item is 3
Item is 4
onCompleted
看到这里可能你又要说了,大兄弟你别唬我啊!OnSubscribe的call()方法中的参数Subscriber怎么就变成了subscribe()方法中的观察者Observer?!!!这俩儿货明明看起来就是两个不同的类啊。
我们先看看Subscriber这个类:
public abstract class Subscriber<T> implements Observer<T>, Subscription {
...
}
从源码中我们可以看到,Subscriber是Observer的一个抽象实现类,所以我首先可以肯定的是Subscriber和Observer类型是一致的。接着往下我们看看subscribe()这个方法:
public final Subscription subscribe(final Observer<? super T> observer) {
//这里的if判断对于我们要分享的问题没有关联,可以先无视
if (observer instanceof Subscriber) {
return subscribe((Subscriber<? super T>)observer);}
return subscribe(new Subscriber<T>() {
@Override
public void onCompleted() {
observer.onCompleted();}
@Override
public void onNext(T t) {
observer.onNext(t);}});}
我们看到subscribe()方法内部首先将传进来的Observer做了一层代理,将它转换成了Subscriber。
我们再看看这个方法内部的subscribe()方法:
public final Subscription subscribe(Subscriber<? super T> subscriber) {
return Observable.subscribe(subscriber, this);
}
进一步往下追踪看看return后面这段代码到底做了什么。精简掉其他无关代码后的subscribe(subscriber, this)方法是这样的:
private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
subscriber.onStart();
try {
hook.onSubscribeStart(observable,observable.onSubscribe).call(subscriber);
return hook.onSubscribeReturn(subscriber);
} catch (Throwable e) {
return Subscriptions.unsubscribed();}
}
我们重点看看hook.onSubscribeStart(observable,observable.onSubscribe).call(subscriber),
前面这个hook.onSubscribeStart(observable, observable.onSubscribe)返回的是它自己括号内的第二个参数observable.onSubscribe,然后调用了它的call方法。而这个observable.onSubscribe正是create()方法中的Subscriber,这样整个流程就理顺了。看到这里是不是对RxJava的执行流程清晰了一点呢?这里也建议大家在学习新技术的时候多去翻一翻源码,知其然还要能知其所以然。
subscribe()的参数除了可以是Observer和Subscriber以外还可以是Action1、Action0;这是一种更简单的回调,只有一个call(T)方法;由于太简单这里就不做详细介绍了!
RxJava的异步:RxJava就是来处理异步任务的。
但是默认情况下我们在哪个线程调用subscribe()就在哪个线程生产事件,在哪个线程生产事件就在哪个线程消费事件。那怎么做到异步呢?RxJava为我们提供Scheduler用来做线程调度,我们来看看RxJava提供了哪些Scheduler。
同时RxJava还为我们提供了subscribeOn()和observeOn()两个方法来指定Observable和Observer运行的线程。
Observable.from(getCommunitiesFromServer())
.flatMap(community -> Observable.from(community.houses))
.filter(house -> house.price>=5000000)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::addHouseInformationToScreen);
上面这段代码大家应该有印象吧,没错正是我们上一篇文章中的例子。
subscribeOn(http://Schedulers.io())指定了获取小区列表、处理房源信息等一系列事件都是在IO线程中运行,
observeOn(AndroidSchedulers.mainThread())指定了在屏幕上展示房源的操作在UI线程执行。
这就做到了在子线程获取房源,主线程展示房源。
好了,RxJava系列的入门内容。下一篇继续介绍更多API以及它们内部原理。