一,RxJava背压策略
1,背压:被观察者发送消息太快以至于它的操作符或者订阅者不能及时处理相关消息,背压是在异步的场景下才会出现,即被观察者和观察者处于不同的线程中。在RxJava2.x中新增了Flowable类型是支持背压的(默认队列大小128),Flowable很多操作符内部也使用了背压策略。
2,Flowable背压策略一共有5种
①,MISSING,此策略表示,通过Create方法创建的Flowable没有指定背压策略,不会对通过OnNext发射的数据做缓存或丢弃处理,需要下游通过背压操作符(onBackpressureBuffer()/onBackpressureDrop()/onBackpressureLatest())指定背压策略。
②,ERROR,此策略表示,如果放入Flowable的异步缓存池中的数据超限了,则会抛出MissingBackpressureException异常。Flowable默认队列是128,这段代码改为128就可以正常运行。
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> e) throws Exception {
for (int i = 0; i < 129; i++) {
e.onNext(i);
}
}
}, BackpressureStrategy.ERROR)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "accept: integer=" + integer);
}
});
③,BUFFER,此策略表示,Flowable的异步缓存池同Observable的一样,没有固定大小,可以无限制添加数据,不会抛出MissingBackpressureException异常,但会导致OOM,这段代码会导致ANR。
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> e) throws Exception {
for (int i = 0; ; i++) {
e.onNext(i);
}
}
}, BackpressureStrategy.BUFFER)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "accept: integer=" + integer);
}
});
④,DROP,此策略表示,如果Flowable的异步缓存池满了,则会丢掉将要放入缓存池中的数据。这段代码不会引起异常,只会打印0~127,第128则被丢弃。
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> e) throws Exception {
for (int i = 0; i<129; i++) {
e.onNext(i);
}
}
}, BackpressureStrategy.DROP)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "accept: integer=" + integer);
}
});
⑤,LATEST,此策略表示,如果缓存池满了,会丢掉将要放入缓存池中的数据。这一点和DROP策略一样,不同的是,不管缓存池的状态如何,LATEST策略会将最后一条数据强行放入缓存池中。这段代码会打印0~127和666,因为666是最后一条数据
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> e) throws Exception {
for (int i = 0; i<667; i++) {
e.onNext(i);
}
}
}, BackpressureStrategy.LATEST)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "accept: integer=" + integer);
}
});
总结:Flowable不仅可以通过create创建时指定背压策略,还可以通过其他操作符创建。例如:just,fromArray等创建后指定背压策略。还可以通过onBackpressureBuffer()对应BackpressureStrategy.BUFFER,onBackpressureDrop()对应Backpressure.DROP,onBackpressureLatest()对应BackpressureStrategy.LATEST。
二,RxJava+Retrofit
1,实现一个网络请求 https://api.douban.com/v2/movie/top250?start=0&count=10 (豆瓣电影测试接口)
先在gradle中配置相关框架
compile 'io.reactivex.rxjava2:rxjava:2.1.3'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.squareup.okhttp3:okhttp:3.9.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
创建请求接口,定义Movie实体
public interface ApiService {
@GET("top250")
Observable<Movie> getTopMovie(@Query("start") int start, @Query("count") int count);
}
创建Retrofit请求
String baseUrl = "https://api.douban.com/v2/movie/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl) .addConverterFactory(ScalarsConverterFactory.create())//请求结果转换为基本类型
.addConverterFactory(GsonConverterFactory.create())//请求的结果转为实体类
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //适配RxJava2.0, RxJava1.x则为RxJavaCallAdapterFactory.create()
.build();
apiService = retrofit.create(ApiService.class);
发送请求,拿到数据
apiService.getTopMovie(0, 10)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Movie>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe: ");
}
@Override
public void onNext(Movie movie) {
//得到数据
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete:");
}
});