RxJava2 基础详解
标签: 网络框架
什么是RxJava
RxJava是Java的响应式编程的扩展,还有一个关键词“异步”
RxJava的自我介绍是:a library for composing asynchronous and event-based programs using observable sequences for the Java VM(一个对于构成使用的Java虚拟机观察序列异步和基于事件的程序库)。很好的阐述了重点“异步”
github:https://github.com/ReactiveX/RxJava
使用RxJava的好处
随着项目代码量慢慢增加,逻辑复杂程度也会渐渐加强,使用RxJava可以帮助我们不管程序逻辑怎样复杂始终保持简洁,因为在调度过程比较复杂的情况下,异步代码经常既难写也难被读懂
RxJava的基本概念
- Observable:发射源,英文释义“可观察的”,在观察者模式中称为“被观察者”或“可观察对象”;
- Observer:接收源,英文释义“观察者”,没错!就是观察者模式中的“观察者”,可接收
Observable
、Flowable
发射的数据;- Flowable:这个也是“被观察者”,咦,怎么又有一个“被观察者”,这个是RxJava2.0新出的用以支持“背压”,关于背压就不做过多解释,可以看关于RxJava最友好的文章——背压(Backpressure)文章;
- Subscriber:“订阅者”,也是接收源,其实也就是“观察者”,支持背压的话以这个和
Flowable
搭配使用,也可以用来当作Observer
使用;- Subscription:Observable调用
subscribe()
方法绑定(订阅)对象,同样有unsubscribe()
方法,可以用来取消订阅事件;- Schedulers:调度器,对于事件产生(Observable)在什么环境和事件处理(Observer)在什么环境进行调度;
添加依赖
//RxJava的依赖包
compile 'io.reactivex.rxjava2:rxjava:2.0.3'
//RxAndroid的依赖包
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
基本流程
- 创建被观察者
Observable observable = Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello"); //onNext-发射数据
subscriber.onNext("RxJava");
subscriber.onCompleted(); //onCompleted-发射完毕的标记
}
});
- 创建观察者
Observer<String> observer = new Observer<String>() {
@Override
public void onCompleted() {
//被观察者调用onCompleted()代表事件发射完毕,并走向这里
Log.i(TAG,"数据发射完毕");
}
@Override
public void onError(Throwable e) {
//发射数据过程中出错会走向这里
Log.i(TAG,"数据出错,错误信息:" + e.getMessage());
}
@Override
public void onNext(String s) {
//发射的数据走向这里
Log.i(TAG,"数据--->"+s)
}
};
观察者有了,被观察者也有了,剩下的就将他们绑定在一起,也就是订阅让他们产生联系;
- 订阅
被观察者-----订阅-----观察者
observable.subscribe(observer);
这我就纳闷了,为什是‘被观察者’去订阅‘观察者’,不是应该反过来的吗?是这样的,逻辑没有错,这样是为了保证链式API调用风格(建造者模式),因为大家想,观察者模式的产生是先有事件产生之后再有‘观察者’对其处理;总不能说什么事都没有而先有‘观察者’处理事件(处理什么事件你们估计也会懵逼),再之后有事件产生;
举个例子:就好比你去超市买一包香烟,正常逻辑是老板问你买什么?你回答买一包什么烟,然后老板就给你什么烟;总不能你一进超市,老板直接给你一包烟,再去问你要什么烟,这样事件的逻辑就不通了
到这时候大家还是会说:是啊,先有事件产生再有事件处理,但还是没解释被观察者订阅观察者这个逻辑啊;
之前不是说了吗,为保证链式API调用风格(建造者模式),如果你想的是观察者订阅被观察者的话,那你是不是得先写观察者?先写观察者?那这样的话是不是与事件逻辑走向相勃;其实这仅仅只是为了保证链式API调用风格,内部实际上还是观察者订阅被观察者;所以大家懂就好。
Tips:基本流程就走到这了
调度 Scheduler
- 调度在之前稍微提到,这是RxJava用以切换线程的调度器,虽然RxJava是异步的,但在不指定线程的情况下, RxJava 遵循的是线程不变的原则,即:在哪个线程调用subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到 Scheduler (调度器)。
调度器类型 | 效果 |
---|---|
Schedulers.computation() | 用于计算任务,如事件循环或和回调处理,不要用于IO操作(IO操作请使用Schedulers.io());默认线程数等于处理器的数量 |
Schedulers.from(executor) | 使用指定的Executor作为调度器 |
Schedulers.immediate() | 在当前线程立即开始执行任务 |
Schedulers.io() | 用于IO密集型任务,如异步阻塞IO操作,这个调度器的线程池会根据需要增长;对于普通的计算任务,请使用Schedulers.computation();Schedulers.io( )默认是一个CachedThreadScheduler,很像一个有线程缓存的新线程调度器 |
Schedulers.newThread( ) | 为每个任务创建一个新线程 |
Schedulers.trampoline( ) | 当其它排队的任务完成后,在当前线程排队开始执行 |
AndroidSchedulers.mainThread() | 是RxAndroid适配于Android系统下的一个方法,用于指定执行在Android主线程中 |
//指定事件产生在io线程中执行
.subscribeOn(Schedulers.io())
//指定事件处理在安卓主线程中执行
.observeOn(AndroidSchedulers.mainThread())
RxJava操作符
RxJava并不仅仅只有上面所说的基本能力,他的操作符才是重点。
- just
可以说是偷懒必备,just
可以接收1~9个参数
//使用just按顺序onNext发射括号的数据,并在发射完毕之后自动调用onCompleted()
Observable.just("Hello","RxJava") //是不是省略了很多代码
.subscribe(new Observer<String>() {
@Override
public void onCompleted() {
//发射结束调用这个方法
}
@Override
public void onError(Throwable e) {
//出现错误会调用这个方法
}
@Override
public void onNext(String s) {
//发射的数据在这个方法
}
);
- from
from
接收一个数组或集合对象,按顺序发送对象中的每个子元素(item),just
也可以接收集合,但just
发送的是整个集合对象
//定义一个数组
String[] str = {"Hello","RxJava"};
//from自动拿出数组str中的每个子元素发送出去
Observable.from(str)
.subscribe(new Observer<String>() {
@Override
public void onCompleted() {
//发射结束调用这个方法
}
@Override
public void onError(Throwable e) {
//出现错误会调用这个方法
}
@Override
public void onNext(String s) {
//发射的数据在这个方法
}
);
- map
产生事物不是理想的目标结果,可以用map
对其在发射之前中转操作
//比如被观察者发送一个图片路径,但观察者要的是直接一张图片
Observable.just(getFilePath())
//使用map操作来完成类型转换
.map(new Func1<String, Bitmap>() { //指定泛型,String是图片路径,Bitmap是图片
@Override
public Bitmap call(String s) {
//将图片路径转换成一张图片
return createBitmapFromPath(s);
}
})
.subscribe(new Subscriber<Bitmap>() {
@Override
public void onCompleted() {
//发射完毕调用此方法
}
@Override
public void onError(Throwable e) {
//出现错误会调用这个方法
}
@Override
public void onNext(Bitmap s) { //发射过来的就是一张图片
//直接显示图片
}
);
- flatmap
这个就比较难懂了,简单说就是将每个Observable产生的事件里的信息再包装成新的Observable传递出来
举个例子,查找一个学校的所有班级的每个学生的姓名,那就可以这样:
//创建被观察者,获取所有班级
Observable.from(school)
.flatMap(new Func1<Class, Observable<String>>() {
@Override
public Observable<String> call(Class Class) {
//每个班级的所有学生姓名装成一个数组或集合,再封成新的Observable,通过from这个集合发射数据
return Observable.from(Class.getStudentName());
}
})
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
//发射完毕,调用此方法
}
@Override
public void onError(Throwable e) {
//出现错误会调用这个方法
}
@Override
public void onNext(String string) {
//发射过来的是每个学生的姓名
}
);
结尾
对于RxJava只写到这了,毕竟本人对于RxJava只懂这么多。
后记
本人那渣渣文字功底确实不好见人,有些说明措辞是参照部分大牛的说法进行揉杂的,结果就这样了
可以参照关于 RxJava 最友好的文章—— RxJava 2.0 全新来袭的文章再去仔细看看,很好理解的一篇文章。