rxjava目前其实已经更新到2.0版本了,但我还是想从1.0开始学习下如何使用,其实你知道了1.0版本如何使用,2.0版本也是知道了,不可能改的面目全非,rxjava是一个异步框架,比如我们android中请求一个网络然后通知ui更新,如果使用最原始的方法就时new一个Thread然后结合Handler去更新UI,但是如果你使用了rxjava就不比这么麻烦了,学习一个框架如何使用就是在github上看它的文档然后结合它给的demo,自己实现一遍就知道的差不多了,我说的是使用,而不是理解里面的源码
地址在这里:https://github.com/ReactiveX/RxAndroid/tree/1.x
rxjava框架的引入在github上也有讲:在build.grade下引入这二个包
compile 'io.reactivex:rxandroid:1.2.1' // Because RxAndroid releases are few and far between, it is recommended you also // explicitly depend on RxJava's latest version for bug fixes and new features. compile 'io.reactivex:rxjava:1.1.6'就这么简单的就引入了rxjava1.0
rxjava是响应式编程,所谓响应式,就是存在二部分,一部分负责发送事件或者消息,另一部分负责接收事件或者消息
rxjava其实入门使用并不像其他框架使用起来那么简单,主要是和我门Java面向对象的思维方式不一样导致的,今天通过这篇博客,希望看到的人都能很好的入门。
rxjava核心原理是使用了扩展的观察者模式,就一般的观察者模式我们都知道,比如马云爸爸喜欢看今日头条,但是他喜欢怀旧,而不是用手机看,喜欢看纸装的那种,那马云爸爸那么忙,不可能每天去报摊上去买,而且也不可能,毕竟现在比一些娱乐明星还红,所以就按一年的去订,只要有新的报纸出来,就会有报童主动送到马云爸爸家里,类似如图:
从上面的图中我们可以根据描述以及图提取几个关键的概念:
上面的订阅操作就把观察者和被观察者关联了起来.
从上面的举例中发现观察者要具备三个因素
第一:被观察者
第二:观察者
第三:订阅(让观察者和被观察者产生关联的动作)
把上面的三条翻译成Java开发认识的观察者是observer,被观察者是Observable,订阅就是subscribe.那我们就把这三个条件同样用于rxjava学习当中.
那现在根据上面三个条件开始学习rxjava使用
第一步:创建被观察者
//今日头条报社 被观察者(Observable) Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { } });第二步:创建观察者
//家庭 观察者(Observer) Observer<String> observer = new Observer<String>(){ @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { } };有了上面二步,但是这并没有让观察者和被观察者产生关联,这个时候他们二个并没有如何联系,所以还需要第三步
第三步:关联(让观察者和被观察者产生关联)也就是订阅了
observable.subscribe(observer);
这个时候如果被观察者也就是Observale发出了什么消息,观察者Observer就会收到什么消息了.那被观察者也就是Observale怎么发送消息呢?这样的:
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { //onNext就相当于subscriber要发送报纸的 subscriber.onNext("hello world rxjava"); } });而切切我们观察者Observer中刚好也有个OnNext()方法,这就是观察者接受到被观察者发送的消息了,也就是说报社发送了报纸,马云爸爸接受到了报纸,这是说这个报纸是一个string类型而已,当然这个由你自定义定义了.
Observer<String> observer = new Observer<String>(){ @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { //接受到被观察者发送的消息 Log.e(TAG,"接收到被观察者发送的消息是"+s); } };下面onNext()方法中s就是被观察者发送出来的消息了,所以呢?onNext()方法对Observale是发送消息的行为,而对Observer来说是接受消息的行为
它的原理是这样的:
当然我们可以在Observale下可发出多个消息这是可以的.
我们在Observer(观察者)的回调当中是有三个方法的,分别是onCompleted(),onNext(),onError(),如果你打log去看的话,其实当接收到消息后其实并没有回调onCompleted(),是的,并不会,那要追踪到Observale发送消息的了,再次看下这个代码:
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { //onNext就相当于subscriber要发送报纸的 subscriber.onNext("hello world rxjava"); } });看下Subscriber类中都有啥方法:
public abstract class Subscriber<T> implements Observer<T>, Subscription {它是一个抽象的类,实现了二个接口,看下Observer这个接口有啥方法:
也就是说Subscriber类中也有这三个方法,再想到我们发送消息用的是onNext(),这个时候如果在onNext()之后调用onCompleted()方法的话Observer的onCompleted()方法就会执行,比如你有个网络请求,当你拿到服务器返回的数据后,要做其他的事情的话,就可以在OnCompleted()回调中去做其他的业务.当你执行了onCompleted()方法以后你再调用onNext()方法,Observer是接收不到消息的,相当于取消了订阅
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { //onNext就相当于subscriber要发送报纸的 subscriber.onNext("hello world rxjava"); subscriber.onCompleted(); subscriber.onNext("再次发送hello world rxjava"); } });第二个消息是受不到的,自己可以打log去看结果,来验证我的说法,
结论:只要调用了onCompleted()后面的事件就收不到
还有一个方法就是OnError()了,这个在你发送异常的时候进行回调的.
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { //onNext就相当于subscriber要发送报纸的 subscriber.onNext("hello world rxjava"); subscriber.onError(new NullPointerException()); subscriber.onNext("再次发送hello world rxjava"); subscriber.onCompleted(); } });你会发现一旦调用了onError()方法,就不会再发送下面的消息了
结论:一旦调用了onError()方法,就不会再发送下面的消息了
特殊的被观察者(Single)
Single它作为被观察者只能发送一次,订阅就终止了,不像Observale有onCompleted(),onNext(),onError()这方法,它发送是通过onSuccess()发送成功,或者调用onError()发送失败,
public void signle(View view){ Single single = Single.create(new Single.OnSubscribe<String>(){ @Override public void call(SingleSubscriber<? super String> singleSubscriber) { singleSubscriber.onSuccess("发送消息11111111111"); singleSubscriber.onSuccess("发送消息2222222222222222"); } }); Observer observer = new Observer<String>() { @Override public void onCompleted() { Log.e(TAG,"onCompleted"); } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { Log.e(TAG,"接收到的消息s="+s); } }; single.subscribe(observer); }log:
从log我们也发现Single只能发送一次消息或者事件,而且观察者接受到了以后会调用onCompleted()方法,其实我们是发送了二次消息的,如果有特殊的需求是可以用这个的,有点类似我们的单例
总结:Single只能发送一次消息也就是只能调用一次OnSuccess()或者onError()
特殊的观察者
我们通常使用的观察者是Observer,其实还有一种,进入Observale类找到subscribe()方法,他有几个重载方法:
public final Subscription subscribe(Subscriber<? super T> subscriber) { // validate and proceed if (subscriber == null) { throw new IllegalArgumentException("observer can not be null"); }传递的是Subscribe这个对象,
public abstract class Subscriber<T> implements Observer<T>, Subscription {发现他其实是Observer的子类,所以也是可以的,写个demo玩玩
//另一种观察者 public void subscriber(View view){ Observable observable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("今天周一好蛋疼"); subscriber.onCompleted(); } }); Subscriber subscriber = new Subscriber<String>() { @Override public void onCompleted() { Log.e(TAG,"onCompleted"); } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { Log.e(TAG,"接收到的消息是::::"+s); } }; observable.subscribe(subscriber); }log:
结果是和Observer一样的,他们的区别在于Subscriber 提供了取消订阅和判断是否已经订阅了,如果有一种需求就是如果消息接受到了话要取消订阅的话,就使用这个.
其实我们开发中可能就只要接受消息的onNext()方法即可,希望不要onCompleted()和onError()方法,不用放在那里,挺不好看的,这个也是可以做到的,我们看下Observale给我们提供的方法:
public final Subscription subscribe(final Action1<? super T> onNext)
public final Subscription subscribe(final Action1<? super T> onNext, final Action1<Throwable> onError) {
public final Subscription subscribe(final Action1<? super T> onNext, final Action1<Throwable> onError, final Action0 onCompleted) {有这三个重载的方法可以给我们使用,现在玩下:
public void onNext(View view){ Observable observable = Observable.create(new OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("今天周一好蛋疼"); subscriber.onCompleted(); } }); Action1 onNext = new Action1<String>(){ @Override public void call(String s) { Log.e(TAG,"接收到的消息是:::"+s); } }; Action1 onError = new Action1<Throwable>(){ @Override public void call(Throwable throwable) { Log.e(TAG,"接收到异常:::"+throwable.toString()); } }; Action0 onCompleted = new Action0(){ @Override public void call() { Log.e(TAG,"消息发送完毕:::"); } }; //只接受onNext() observable.subscribe(onNext); }log:
至于你还想接受onCompleted事件的话,上面已经写好了,传递进去就行了.上面用到了如果没有参数就是Action0,一个参数是Action1,他们就是Action的实现类,看下Action这个接口有多少实现类:
都到9了,因为没有10,呵呵,还有个ActionN就是要你自己自定义了,一般很难用到,在这也是说一下而已.
public interface ActionN extends Action { void call(Object... args); }他接受的是一个可变参数。和Action对应的还有个Func0到Func9,写个demo玩下:
Func0 f0 = new Func0<String>(){ @Override public String call() { return null; } }; Func1 f1 = new Func1<String,Integer>(){ @Override public Integer call(String s) { return null; } };
Func也有从0到9,他的call()方法是有返回值的,返回值是泛型的最后一个.
雌雄同体的Subject
为什么说Subject是雌雄同体呢?看下它的类结构就知道了,
它即继承了Observable,又实现了Observer接口,所以Subject即是观察者又是被观察者,这是冷战时期的双面间谍,但是一般都是使用它作为被观察者,也就是说当做Observable用,他是一个抽象类,来看看给我们提供了什么子类使用,
有8个子类啊,先看第一个子类,介绍下有啥用
AsyncSubject
如果你点击进去看了他的注释,代码都给你写好了,直接copy出来运行下就行,文档还是很不错的,
public void asyncsubject(View view){ AsyncSubject<String> subject = AsyncSubject.create(); subject.onNext("one"); subject.onNext("two"); subject.onNext("three"); subject.onCompleted(); Action1<String> action1 = new Action1<String>() { @Override public void call(String s) { Log.e(TAG,"接受到的消息是:::"+s); } }; subject.subscribe(action1); }log:
你会看到他只接受了额一个消息,但是我们发送的是三个消息对吧,这就是AsyncSubject这个对象的特点,
AsyncSubject特点:只会接受一个消息,就是发送的最后一个消息,从类的类名就可以看的出来,他是异步的,也就是说不等调用subscribe()方法,创建后就可以发送消息了,如果你不调用onCompleted()发送,是发送不出任何一个消息的,
BehaviorSubject
学习这个类也是从他的类注释已经给我们写好了demo,copy过来
public void behaviorsubject(View view){ BehaviorSubject<String> subject = BehaviorSubject.create("default"); Action1<String> action1 = new Action1<String>() { @Override public void call(String s) { Log.e(TAG,"接受到的消息是:::"+s); } }; subject.onNext("zero"); subject.onNext("one"); subject.subscribe(action1); subject.onNext("two"); subject.onNext("three"); }log:
zero,one是订阅前发送的, two,thred是订阅后发送的,但是他并没有打印zero。所以他的特点就出来了,会发送订阅前最后一个和订阅后所有的事件;现在我订阅前一个事件都不发送,再试试
public void behaviorsubject(View view){ BehaviorSubject<String> subject = BehaviorSubject.create("default"); Action1<String> action1 = new Action1<String>() { @Override public void call(String s) { Log.e(TAG,"接受到的消息是:::"+s); } }; subject.subscribe(action1); subject.onNext("two"); subject.onNext("three"); }log:
所以啊,如果订阅前不发送任何事件的话,就会发送默认一个事件了
结论:BehaviorSubject会发送订阅前最后一个和订阅后所有的事件,如果订阅前没有任何事件发送的话,就会发送默认事件了
PublishSubject
同样的学习方法,把他的类注释上的代码copy过来
public void publishsubject(View view){ PublishSubject<String> subject = PublishSubject.create(); Action1<String> action1 = new Action1<String>() { @Override public void call(String s) { Log.e(TAG,"接受到的消息是:::"+s); } }; subject.onNext("one"); subject.onNext("two"); subject.subscribe(action1); subject.onNext("three"); subject.onNext("four"); subject.onCompleted(); }log:
你会发现明明我是发送了四个事件,但是只接收到了最后二个,最后二个是在订阅后发送的,是的,他也是在创建后就可以发送事件,但是观察者只接受到他订阅后的事件
结论:PublishSubject创建后就可以发送事件,但是观察者只能接收到他订阅后发送的事件
ReplaySubject
同样的学习方法,从类注释上copy他的例子
public void replaysubject(View view){ ReplaySubject<String> subject = ReplaySubject.create(); Action1<String> action1 = new Action1<String>() { @Override public void call(String s) { Log.e(TAG,"接受到的消息是:::"+s); } }; subject.onNext("one"); subject.onNext("two"); subject.subscribe(action1); subject.onNext("three"); subject.onCompleted(); }log:
从这log中我们很好的知道,不管什么时候发送事件,观察者都能接收到
结论:ReplaySubject不管在订阅后还是前发送事件,观察者都能接受到
接下来就开始学习各种操作符了
publish操作符
是将一个普通的被观察者变成一个可连接的被观察者
public void publish(View view){ Observable<String> observable = Observable.create(new OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("hello world rxjava"); subscriber.onCompleted(); } }); //通过publish操作符变成一个可连接的observable ConnectableObservable connectableObservable = observable.publish(); Observer<String> observer = new Observer<String>(){ @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { Log.e(TAG,"接收到被观察者发送的消息是"+s); } }; connectableObservable.subscribe(observer); }你会发现啥都不会打印,也就是说Observable中的call()方法并没有调用,想要调用的话,还要添加如下代码:
connectableObservable.connect();
是在subscribe()方法之后调用才有效.这个时候再运行起来,log
publish操作符的作用就是帮助我们想要发送的事件统一发送,在调用connect()之后订阅观察者是接受不到消息的
其实Observable和ConnectableObservable是可以互相转换的,如图
replay操作符
上面的publish操作是一个普通的Observable变成一个可连接的ConnectableObservable,但是有个缺点就是在调用connect()方法之后在订阅的话,是接收不到消息的,如果想要接收到被观察者发送的消息的话,就要使用replay操作符了
public void replay(View view){ Observable<String> observable = Observable.create(new OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("hello world rxjava"); subscriber.onCompleted(); } }); //通过replay操作符变成一个可连接的observable ConnectableObservable connectableObservable = observable.replay(); Observer<String> observer = new Observer<String>(){ @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void