一.关键字:ObservableEmitter
.create(observableEmitter->{//就是这个东西
//....
})
Emitter就是发射器的意思,该发射器可以:onNext(),onComplete()和onError()
注意:
- 上游无限onNext,下游无限接收onNext
- 上游发送onComplect,此时的下游收到onComplect事件后不再继续接收事件
- 上游发送onError,此时下游不再接收事件
- 上游也可以不发送onComplete和onError
- onComplete和onError唯一并且互斥
二.关键字:Dispisable
中文:Disposable–一次性的,可任意处理的,免洗的:
这个相当于上下游管子的一个机关,他可以切断管道
调用dispose()并不会导致上游不再发送事件,上游会继续发送剩余的事件;但是下游不再接收
new Observer<Integer>() {
private Disposable mDisposable;
private int i;
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "subscribe");
mDisposable = d;
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "onNext: " + value);
i++;
if (i == 2) {
Log.d(TAG, "dispose");
mDisposable.dispose();
Log.d(TAG, "isDisposed : " + mDisposable.isDisposed());
}
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "error");
}
@Override
public void onComplete() {
Log.d(TAG, "complete");
}
}
Disposable可以切断下游的接收,但是上游依然会执行
Disposable的用处不止这些,线程的调度依然会使用他
三.线程的调用:将上游的管子放在子线程里面
observable.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(consumer);
简单的来说:subscribeOn():指定上游事件的线程
oberveOn():指定下游接收事件的线程
observable.subscribeOn(Schedulers.newThread())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.observeOn(Schedulers.io())
.subscribe(consumer);
subscribeOn:只有第一次指定的有效
observeOn:则是最后一次有效
observable.subscribeOn(Schedulers.newThread())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG, "After observeOn(mainThread), current thread is: " + Thread.currentThread().getName());
}
})
.observeOn(Schedulers.io())
.doOnNext(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG, "After observeOn(io), current thread is : " + Thread.currentThread().getName());
}
})
.subscribe(consumer);
结果:
D/TAG: Observable thread is : RxNewThreadScheduler-1
D/TAG: emit 1
D/TAG: After observeOn(mainThread), current thread is: main
D/TAG: After observeOn(io), current thread is : RxCachedThreadScheduler-2
D/TAG: Observer thread is :RxCachedThreadScheduler-2
D/TAG: onNext: 1
其实就是水管一样切换了,后面就一直是这样了
四.在Rxjava中,内置了线程选项供我们选择:
代码 | 应用 |
---|---|
Schedules.io() | 代表io操作的线程,用于网络,文件读写等io密集 |
Schedules.computation | 代表CPU计算密集型 |
Schedules.newThread() | 常规新线程 |
AndroidSchedulers.mainThread() | Android的主线程 |
五.网络请求奔溃和Disposable
Api api = retrofit.create(Api.class);
api.login(request)
.subscribeOn(Schedulers.io()) //在IO线程进行网络请求
.observeOn(AndroidSchedulers.mainThread()) //回到主线程去处理请求结果
.subscribe(new Observer<LoginResponse>() {
@Override
public void onSubscribe(Disposable d) {}
@Override
public void onNext(LoginResponse value) {}
@Override
public void onError(Throwable e) {
Toast.makeText(mContext, "登录失败", Toast.LENGTH_SHORT).show();
}
@Override
public void onComplete() {
Toast.makeText(mContext, "登录成功", Toast.LENGTH_SHORT).show();
}
});
如上图,我们需要Disposable#dispose()方法切断水管,使得下游收不到事件,因此我们可以在Activity中将这个disposable保存起来,在Activitiy退出时候,切断即可;
假如有多个disposable.rxjava内置了一个容器CompositeDisposable,每当我们得到一个Disposable使用CompositeDisposable#add()将他添加,退出的时候调用CompositeDisposable#clear()切断
六.操作符号:Map
作用:就是对上游发送的每一个事件应用一个函数,使得每个事件都按照指定的函数去变化
如图:map就是将圆形事件转换成矩形事件,从而导致下游接收的事件变成矩形
Observable.create((ObservableOnSubscribe<Integer>) emitter -> {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}).map(integer -> "This is result " + integer)
.subscribeOn(Schedulers.io())
.subscribe(new Observer<String>() {
private Disposable mDisposable;
private int i;
@Override
public void onSubscribe(Disposable d) {
mDisposable = d;
}
@Override
public void onNext(String integer) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
上面就是把圆形事件(Interger)变成矩形事件(String)了
七. 操作符:FlatMap(不保证顺序) concatMap(保证顺序)
作用:将上游Obervable变换成多个发送事件的Observalbes,然后将他们发射的事件合并在一个单独的Obervable里面:
上游每发送一个事件,flatMap都将创建一个新的水管,然后发送转换之后的新的事件,下游接收的就是新的水管发送的数据.不过:flatMap并不保证事件的顺序,;如果需要保证顺序的话,需要使用concatMap
如:
Observable.create((ObservableOnSubscribe<Integer>) emitter -> {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}).flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
final List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("I am value " + integer);
}
return Observable.fromIterable(list).delay(10, TimeUnit.MICROSECONDS);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("tag", s);
}
});
结果:
D/TAG: I am value 1
D/TAG: I am value 1
D/TAG: I am value 1
D/TAG: I am value 3
D/TAG: I am value 3
D/TAG: I am value 3
D/TAG: I am value 2
D/TAG: I am value 2
D/TAG: I am value 2
可以看出没有按照onNext的顺序执行,当我们把flatMap编程concatMap的时候
D/TAG: I am value 1
D/TAG: I am value 1
D/TAG: I am value 1
D/TAG: I am value 2
D/TAG: I am value 2
D/TAG: I am value 2
D/TAG: I am value 3
D/TAG: I am value 3
D/TAG: I am value 3
就完成按照onNext 的顺序执行
九.实践:注册–>登录一气呵成是怎么样的?
接口:
public interface Api {
@GET
Observable<LoginResponse> login(@Body LoginRequest request);
@GET
Observable<RegisterResponse> register(@Body RegisterRequest request);
}
使用:
api.register()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doONext(result->{
}).observeOn(Schedulers.io)
.flatMap(result->{
return api.login(result)
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(loginResult->{
},error->{
})
这里的flatMap可以使用concatMap代替,其实可以理解为多个io操作的顺序执行
十.Flowable
我们知道,当上游一次性发送超过128个事件的时候,会抛MissingBackpressureException,的异常,怎么解决呢?
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
for (int i = 0; i < 1000; i++) {
Log.d(TAG, "emit " + i);
emitter.onNext(i);
}
}
}, BackpressureStrategy.BUFFER)
使用 BackpressureStrategy.BUFFER就是在内存不oom的情况下,无限的事件大小;
而BackpressureStrategy.DROP 和BackpressureStrategy.LATEST 策略是下游不处理就抛弃,后者是最后一个不抛弃;
Flowable 有特殊的使用
lowable.interval(1, TimeUnit.MICROSECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Long>() {
}
这样会直接抛MissingBackpressureException异常
这是因为我们每个给定BackPressure的策略
使用:
onBackpressureBuffer()
onBackpressureDrop()
onBackpressureLatest()
就可以了
Flowable.interval(1, TimeUnit.MICROSECONDS)
.onBackpressureDrop() //加上背压策略
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Long>() {
@Override
public void onSubscribe(Subscription s) {
Log.d(TAG, "onSubscribe");
mSubscription = s;
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(Long aLong) {
Log.d(TAG, "onNext: " + aLong);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onError(Throwable t) {
Log.w(TAG, "onError: ", t);
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete");
}
});