前言
- 函数式编程:函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值),和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。和过程化编程相比,函数式编程里函数的计算可随时调用。
RXJava
- 当我们的异步网络请求用的越来越多的时候,rxjava是一种能依旧让我们的逻辑保持清晰的操作,他的原理就是创建一个Observable对象来干活,然后使用各种操作符建立起来的链式操作,就如同流水线一样,把你的数据一步一步加工,最终达到想要的效果。
- rxjava的异步操作是通过扩展的观察者模式来实现的,rxjava有四个角色,Observable,Observer,Subscriber和Subject,其中Observable和Observer通过Subscriber方法实现订阅关系,Observable就可以在需要的时候通知Observer。
- 其实RxJava是通过扩展的观察者模式来实现的,不了解观察者模式的童鞋可以移驾这里
- emmmmm,还是等会代码解释
使用前添加依赖
implementation "io.reactivex.rxjava2:rxjava:2.x.y"
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
- 具体版本直接上git官方查看就ok
- 其中RxAndroid是RxJava在android平台上的扩展,它包含了一些能够简化Android开发的工具,比如特殊的调度器
一.使用入门
1.创建Observer(观察者)
Observer<String> mObserver = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.d(TAG, "onNext: 我是张三,他给我发的消息是 message = " +s );
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
2.创建被观察者(Observable)
Observable<String> mObservable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("这是第一条消息");
emitter.onNext("我来发射数据");
emitter.onComplete();
}
});
3.订阅(subscribe)
mObservable.subscribe(mObserver)
- 订阅的方式很简单,就是用被观察者调用subscribe方法来订阅观察者
4.运作方式
- 在我们订阅的时候,实际上就是调用的被观察者在创建的时候我们实现的ObservableOnSubscribe接口的匿名类的subscriber方法
- 不过此时并不是立即调用我们实现的subscribe方法里面的逻辑,先调用的是观察者的onSubscribe方法
- 然后再去运行Subscribe方法里面的逻辑
- 而Subscribe方法的参数emitter实际上就是我们在订阅的时候传入的观察者实例
- 所以我们在被观察者里面调用的emitter.onNext(“这是第一条消息”);实际上就是回调的是观察者的onNext方法
- 当运行异常的时候,观察者的onError方法就会被调用,同时事件队列自动终止,不允许再有事件发出
- complete方法是在事件完毕之后执行,不过在这种方式之下我们需要手动去调用,就像我上面写的
5.其他的创建被观察者的方式
(1).Just方式
mObservable = Observable.just("这是just方式创建的被观察者发送的事件");
- 这里的just参数将直接被作为Onserver的onNext方法的参数传入
- 所以在mObservable.subscribe(mObserver);之后,log打印出来的信息就是
onSubscribe:
onNext: 我是张三,他给我发的消息是 message = 这是just方式创建的被观察者发送的事件
onComplete:
- 这里不清楚为什么这里的complete方法得到了执行,百思不得其解
- 这里的just方式是重载了十个方法,分别对应一个参数,两个参数,…一直到十个参数
List<String> list = new ArrayList<>();
for(int i = 0 ; i < 10 ;i++){
list.add("我是formIterable方式创建的第 " + i+ " 条消息");
}
mObservable = Observable.fromIterable((Iterable<String>)list);
onSubscribe:
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 0 条消息
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 1 条消息
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 2 条消息
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 3 条消息
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 4 条消息
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 5 条消息
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 6 条消息
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 7 条消息
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 8 条消息
onNext: 我是张三,他给我发的消息是 message = 我是formIterable方式创建的第 9 条消息
onComplete:
- 所以说,这里的list集合其实就相当于我们上面在just里面传入的多条参数
- 而且, Collection接口是Iterable接口的子接口,所以所有Collection接口的实现类都可以作为Iterable对象直接传入fromIterable()方法。
(3).defer方式
mObservable = Observable.defer(new Callable<ObservableSource<? extends String>>() {
@Override
public ObservableSource<? extends String> call() throws Exception {
return Observable.just("我是defer方式创建的被观察者","我也是defer方式创建的被观察者");
}
});
onSubscribe:
onNext: 我是张三,他给我发的消息是 message = 我是defer方式创建的被观察者
onNext: 我是张三,他给我发的消息是 message = 我也是defer方式创建的被观察者
onComplete:
(4).interval方式
Observable<Long> o = Observable.interval(4, TimeUnit.SECONDS);
o.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "interval方式创建 onSubscribe: ");
}
@Override
public void onNext(Long aLong) {
Log.d(TAG, "interval方式创建 onNext: 他给我发的数字是 " + aLong);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "interval方式创建 onError: ");
}
@Override
public void onComplete() {
Log.d(TAG, "interval方式创建 onComplete: ");
}
});
- 这种方式的作用时就像定时器一样,按照我们在interval里面设置的时长间隔发送从0开始的整数序列
- 因为他所需要的泛型是长整型,所以这里我重新创建了一个被观察者,并且在订阅的时候重新创建了一个观察者,由于我在interval里面写的是4,TimeUnit.SECONDS,所以他将每隔四秒发送一个整型值,所以打出的log为
interval方式创建 onSubscribe:
interval方式创建 onNext: 他给我发的数字是 0
interval方式创建 onNext: 他给我发的数字是 1
interval方式创建 onNext: 他给我发的数字是 2
interval方式创建 onNext: 他给我发的数字是 3
interval方式创建 onNext: 他给我发的数字是 4
interval方式创建 onNext: 他给我发的数字是 5
interval方式创建 onNext: 他给我发的数字是 6
- 这个方法正常情况是不会主动执行complete方法的,因为他会一直发送下去
(5).range方式
Observable<Integer> observable = Observable.range(1,5);
observable.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe: ");
}
@Override
public void onNext(Integer integer) {
Log.d(TAG, "onNext: 这次他发送的数字是 " + integer);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: ");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete: ");
}
});
- 还是因为他只接受整型或长整型泛型的Observer,所以我重新创建了观察者
- 其中range的第一个参数表示开始发送的数字,第二个参数表示发送的个数,看一下log的信息
onSubscribe:
onNext: 这次他发送的数字是 1
onNext: 这次他发送的数字是 2
onNext: 这次他发送的数字是 3
onNext: 这次他发送的数字是 4
onNext: 这次他发送的数字是 5
onComplete:
(7).Timer方式
Observable<Long> observable1 = Observable.timer(2, TimeUnit.SECONDS)
observable1.subscribe(mLongObserver)
- 啊,这里我没再去创建一个Long泛型的Observer,而是在外面创建了一个私有变量,啊,这些不管
- 这种方式的timer的参数为延迟第一个参数为第二个参数为单位的时间,发送一个东西(额,我也不知道发什么东西,反正就是延迟这么长时间,调用观察者的onNext方法)
- 看一下他的log信息
onSubscribe:
onNext: 0
onComplete:
(8).repeat方式
- 这种方式就是将以上几种方式一直重复,比如说我重复TImer
Observable<Long> observable2 = Observable.timer(3, TimeUnit.SECONDS).repeat();
observable2.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe: ");
}
@Override
public void onNext(Long integer) {
Log.d(TAG, "onNext: " + integer);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: ");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete: ");
}
});
onSubscribe:
onNext: 0
onNext: 0
onNext: 0
onNext: 0
onNext: 0
onNext: 0
- 那么他就会一直重复Timer这个动作,至于其他的也一样,只需要给后面加一个repeat就可以
6.简单部分补充
- 我们在使用订阅方法的时候,常常看到有好几个重载的subscriber方法
public final Disposable subscribe() {}
表示观察者不对被观察者发送的事件作出任何响应(但被观察者还是可以继续发送事件)
public final Disposable subscribe(Consumer<? super T> onNext) {}
表示观察者只对被观察者发送的Next事件作出响应
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {}
表示观察者只对被观察者发送的Next事件 & Error事件作出响应
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete) {}
表示观察者只对被观察者发送的Next事件、Error事件 & Complete事件作出响应
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Disposable> onSubscribe) {}
表示观察者只对被观察者发送的Next事件、Error事件 、Complete事件 & onSubscribe事件作出响应
public final void subscribe(Observer<? super T> observer) {}
表示观察者对被观察者发送的任何事件都作出响应
- 我们可以看到,最后一种是我们基本使用的那种
- 第一种表示当调用之后,只调用被观察者实现的subscribe方法中除过事件之外的其他语句
- 比方说
mObservable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
Log.d(TAG, "subscribe: 我要发送第一条消息啦");
emitter.onNext("这是第一条消息");
Log.d(TAG, "subscribe: 我要发送第二条消息啦");
emitter.onNext("我来发射数据");
}
});
- 如果我们的被观察者这样写,那么当mObservable.subscriber()之后,只会执行两个log语句,而不会指向其他的两个语句
- 第二个到第四个方法,代表我们只实现简单的观察者,这里我写全的最后一个方法的调用方式为
Observable<String> observable = Observable.just("我是消息");
observable.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d(TAG, "accept: " + s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.d(TAG, "accept: Error");
}
}, new Action() {
@Override
public void run() throws Exception {
Log.d(TAG, "run: complete");
}
}, new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
Log.d(TAG, "accept: Subscriber");
}
});
- 其中,subscriber方法第一第二第四个参数分别实现Consumer接口,第三个参数实现Action接口
- 当我按照上面所写的话,打印出来的log为
accept: Subscriber
accept: 我是消息
run: complete
- 可以看出,第一个参数表示我们观察者的onNext方法调用,第二个相当于onError方法调用,第三个参数代表complete方法调用,第四个参数相当于subscriber方法调用
- 由四个不同的重载方法比较得出,我们可以只实现第一个参数的方法,那么他相当于只执行观察者的onNext方法,以此类推
7.中断观察者与被观察者的连接
- 通过这种方式我们可以中断观察者与被观察者的连接,也就是说被观察者你爱发不发,我都可以通过这种方式来不去接收你的消息
Observable<String> observable = Observable.just("我是消息1","我是消息2","我是消息3","我是消息4");
observable.subscribe(new Observer<String>() {
private Disposable mDisposable;
private int cnt = 0;
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe: 拦截器赋值");
mDisposable = d;
}
@Override
public void onNext(String s) {
cnt++;
Log.d(TAG, "onNext: 我收到了第 "+ cnt +" 条消息 == "+s);
if(cnt > 2){
Log.d(TAG, "onNext: 好了,我已经中断连接了");
mDisposable.dispose();
}
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: ");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete: ");
}
});
onSubscribe: 拦截器赋值
onNext: 我收到了第 1 条消息 == 我是消息1
onNext: 我收到了第 2 条消息 == 我是消息2
onNext: 我收到了第 3 条消息 == 我是消息3
onNext: 好了,我已经中断连接了
8.简单小结
- 可以看到,RxJava的整个运作流程大概是这样的
- 被观察者 (Observable) 通过 订阅(Subscribe) 按顺序发送事件 给观察者 (Observer), 观察者(Observer) 按顺序接收事件 & 作出对应的响应动作
- 同时我们也可以分开分别实现带四个参数的subscriber方法,将我们的观察者的四个方法分开
- 同时,在合适的地方采取合适的中断连接等等