RxJava入门学习
ReactiveX是Reactive Extensions的缩写,一般简写为Rx,(响应式)
extensions 英[ɪks'tenʃnz]
美[ɪks'tenʃnz]
n. 延伸; 扩展名; 延长( extension的名词复数 ); [逻辑学] 外延;
reactive 英[riˈæktɪv]
美[riˈæktɪv]
adj. 反应的; 活性的; 电抗的;
gitHub的地址:
https://github.com/ReactiveX/RxJava
https://github.com/ReactiveX/RxAndroid
首先在as中添加依赖:
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
Rxjava是什么?
RxJava 在 GitHub 主页上的自我介绍是 “a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。
异步操作的库
好处再哪里?
异步操作有AsyncTask和handler,但是RxJava更简洁
假设有这样一个需求:
界面上有一个自定义的视图 imageCollectorView ,它的作用是显示多张图片,并能使用 addImage(Bitmap) 方法来任意增加显示的图片。现在需要程序将一个给出的目录数组 File[] folders 中每个目录下的 png 图片都加载出来并显示在 imageCollectorView 中。需要注意的是,由于读取图片的这一过程较为耗时,需要放在后台执行,而图片的显示则必须在 UI 线程执行。常用的实现方式有多种,我这里贴出其中一种:
new Thread() {
@Override
public void run() {
super.run();
for (File folder : folders) {
File[] files = folder.listFiles();
for (File file : files) {
if (file.getName().endsWith(".png")) {
final Bitmap bitmap = getBitmapFromFile(file);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
imageCollectorView.addImage(bitmap);
}
});
}
}
}
}
}.start();
RaJava的做法:
Observable.from(folders)
.flatMap(new Func1<File, Observable<File>>() {
@Override
public Observable<File> call(File file) {
return Observable.from(file.listFiles());
}
})
.filter(new Func1<File, Boolean>() {
@Override
public Boolean call(File file) {
return file.getName().endsWith(".png");
}
})
.map(new Func1<File, Bitmap>() {
@Override
public Bitmap call(File file) {
return getBitmapFromFile(file);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) {
imageCollectorView.addImage(bitmap);
}
});
代码虽然多了,但是逻辑更简洁。
API 介绍和原理简析
RaJava观察者模式扩展
RxJava使用的是观察者模式
Observable :被观察者(类似于Button、小偷)
Observer :观察者(类似于OnClickListener 、警察)、Subscriber(对Observer 接口进行了一些扩展)
注意:
在 RxJava 的 subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber 再使用
subscribe :订阅(setOnClickListener())
事件:(onClick())
RxJava的回调事件:
onNext() (相当于 onClick() / onEvent())
onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。
onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
基本的实现
Observable的创建:
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Log.d("haha", "subscribe (observable thread) " + Thread.currentThread().getName());
e.onNext(6);
}
});
Observable<Integer> just = Observable.just(3,4,5);
//Observable<Integer> from = Observable.fromArray(3,4,5);
Observer<Integer> observer = new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.d("haha", "onNext (subscriber thread) " + Thread.currentThread().getName());
Log.d("haha", "onNext integer:" + value);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
just.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
Consumer
observable.subscribeOn(Schedulers.io())//上游指定的线程(一般比较耗时的操作)
.observeOn(AndroidSchedulers.mainThread())//下游指定的线程
.subscribe(new Consumer<Drawable>() {
@Override
public void accept(Drawable drawable) throws Exception {
//处理 onNext()
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
//处理 onError()
}
}, new Action() {
@Override
public void run() throws Exception {
//处理 onComplete()
}
});
Scheduler:
final int res = R.mipmap.ic_launcher;
Observable<Drawable> observable = new Observable<Drawable>() {
@Override
protected void subscribeActual(Observer<? super Drawable> observer) {
// 使用drawable资源但不为其设置theme主题
// Drawable drawable = ResourcesCompat.getDrawable(getResources(), res, null);
// 使用默认的activity主题
Drawable drawable = ContextCompat.getDrawable(MainActivity.this, res);
// 使用自定义主题
// ResourcesCompat.getDrawable(getResources(), res, anotherTheme);
// 过时的方法
// Drawable drawable = getResources().getDrawable(res);
observer.onNext(drawable);
observer.onComplete();
}
};
observable.subscribeOn(Schedulers.io())//上游指定的线程(一般比较耗时的操作)
.observeOn(AndroidSchedulers.mainThread())//下游指定的线程
.subscribe(new Consumer<Drawable>() {
@Override
public void accept(Drawable drawable) throws Exception {
mImageView.setImageDrawable(drawable);
}
});
Observable:一般执行比较耗时的操作
Consumer(在Rxjava1.0里是observe):接受Observable onNext()中指定的参数
操作符
range
Observable.range(1,5)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("haha", "integer:" + integer);
}
});
timer
//延迟加载 可以替换 handler.postDelayed
Observable.timer(5, TimeUnit.SECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d("haha ", Thread.currentThread().getName());
}
});
interval
//3秒发送一次,后续每1秒发送一次
Observable.interval(3,1,TimeUnit.SECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d("haha", Thread.currentThread().getName());
}
});
repeat
Observable.just("hello", "world")
.repeat(3)
.subscribe(new DisposableObserver<String>() {
@Override
public void onNext(String value) {
Log.d("haha", value);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.d("haha", "onComplete");
}
});
defer
该操作符能保证订阅执行时数据源是最新的数据。
没用defer:
String src = "taoge";
private void deferDemo() {
Observable<String> observable = Observable.just(src);
DisposableObserver<String> disposableObserver = new DisposableObserver<String>() {
@Override
public void onNext(String value) {
Log.d("haha", value);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
src = "taoge 222";
observable.subscribe(disposableObserver);
}
使用defer:
String src = "taoge";
private void deferDemo() {
Observable<String> observable = Observable.defer(new Callable<ObservableSource<? extends String>>() {
@Override
public ObservableSource<? extends String> call() throws Exception {
return Observable.just(src);
}
});
DisposableObserver<String> disposableObserver = new DisposableObserver<String>() {
@Override
public void onNext(String value) {
Log.d("haha", value);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
src = "taoge 222";
observable.subscribe(disposableObserver);
}
doOnXXX
使用这一组操作符,我们能在使用简单Consumer回调对onNext方法作处理时,依然能对其他三种回调做处理:
doOnSubscribe
在onNext之前做初始化操作。
doOnNext
允许我们在每次输出一个元素之前做一些额外的事情。
doOnError
当出现错误时复写方法做处理
doOnComplete
当onNext执行完时,做最后总处理
在doOnSubscribe()之后,使用subscribeOn()就可以指定其运行在哪中线程。
Observable.just("hello world")
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
Log.d("haha", "doOnSubscribe: " + Thread.currentThread().getName());
}
})
.subscribeOn(Schedulers.io())
.doOnNext(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("haha", "doOnNext: " + Thread.currentThread().getName());
}
})
.doOnError(new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.d("haha", "doOnError: " + Thread.currentThread().getName());
}
})
.doOnComplete(new Action() {
@Override
public void run() throws Exception {
Log.d("haha", "doOnComplete: " + Thread.currentThread().getName());
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("haha", "current thread :" + Thread.currentThread().getName());
}
});
filter
//过滤1-10能整除2的数
Observable.range(1, 10)
.filter(new AppendOnlyLinkedArrayList.NonThrowingPredicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer % 2 == 0;
}
})
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("haha", "integer:" + integer);
}
});
groupby
Observable.range(1, 10)
.groupBy(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
return (integer % 2 == 0) ? "偶数组" : "奇数组";
}
})
.subscribe(new Consumer<GroupedObservable<String, Integer>>() {
@Override
public void accept(GroupedObservable<String, Integer> stringIntegerGroupedObservable) throws Exception {
final String key = stringIntegerGroupedObservable.getKey();
stringIntegerGroupedObservable.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("haha", integer + " is " + key);
}
});
}
});
take
Observable.range(1, 10)
.take(3)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("haha", "integer:" + integer);
}
});
skip
Observable.range(1, 10)
.skip(4)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("haha", "integer:" + integer);
}
});
scan
sacn操作符是遍历源Observable产生的结果,再按照自定义规则进行运算,依次输出每次计算后的结果给订阅者:
Observable.range(1, 10)
.scan(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) throws Exception {
Log.d("haha", "integer = " + integer + " integer2 = " + integer2);
return integer + integer2;
}
})
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("haha", "result :" + integer);
}
});
注意:第一次不参与运算
map:
//将string转化成integer
Observable.just("33")
.map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
return 2017;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer value) throws Exception {
Log.d("haha", "value:" + value);
}
});
Flowable.just("33")
.map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
return 2018;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("haha", "value:" + value);
}
});
flatMap:
//给hello world前面加上字段
Observable.just("hello","world")
.flatMap(new Function<String, ObservableSource<String>>() {
//第一个参数就是just 里面的参数类型,第二个参数就是ObservableSource<?> 其中?是需要转成什么类型的ObservableSource
@Override
public ObservableSource<String> apply(String s) throws Exception {
return Observable.just("good + "+s);
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("haha", "s = "+s);
}
});
map和flatMap的区别:
map:转换成指定的对象发射出去
flatMap:转换成指定对象的ObservableSource发射出去
zip
//用途可以请求两个地址,然后拼接地址
Observable<String> stringObservable = new Observable<String>() {
@Override
protected void subscribeActual(Observer<? super String> observer) {
observer.onNext("taoge");
}
};
Observable<Integer> integerObservable = new Observable<Integer>() {
@Override
protected void subscribeActual(Observer<? super Integer> observer) {
observer.onNext(100);
}
};
Observable.zip(stringObservable, integerObservable, new BiFunction<String, Integer, String>() {
@Override
public String apply(String s, Integer integer) throws Exception {
return s + integer;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("haha", "result = " + s);
}
});
背压(Backpressure)
我们分别创建了两根水管, 第一根水管用机器指令的执行速度来无限循环发送事件, 第二根水管随便发送点什么, 由于我们没有发送Complete事件, 因此第一根水管会一直发事件到它对应的水缸里去
Observable<String> stringObservable =Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("taoge");
}
}) .subscribeOn(Schedulers.io());
Observable<Integer> integerObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
for (int i = 0; ; i++) {
e.onNext(i);
}
}
}).subscribeOn(Schedulers.io());
Observable.zip(stringObservable, integerObservable, new BiFunction<String, Integer, String>() {
@Override
public String apply(String s, Integer integer) throws Exception {
return s + integer;
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("haha", "result = " + s);
}
});
结果:内存一直在上涨
原因:
其中一个水管A发送事件特别快, 而另一个水管B 发送事件特别慢, 那就可能出现这种情况, 发得快的水管A 已经发送了1000个事件了, 而发的慢的水管B 才发一个出来, 组合了一个之后水管A 还剩999个事件, 这些事件需要继续等待水管B 发送事件出来组合, 那么这么多的事件是放在哪里的呢? 总有一个地方保存吧? 没错, Zip给我们的每一根水管都弄了一个水缸,上游发送的所有事件都放到水缸里了, 所以瞬间水缸就满了。
分析了原因怎么解决呢?
两种方案:
一是从数量上进行治理, 减少发送进水缸里的事件
二是从速度上进行治理, 减缓事件发送进水缸的速度
方案一(从数量上控制):只放我们需要的事件到水缸里
Observable<String> stringObservable =Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("taoge");
}
}) .subscribeOn(Schedulers.io());
Observable<Integer> integerObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
for (int i = 0; ; i++) {
e.onNext(i);
}
}
}).subscribeOn(Schedulers.io()).sample(2,TimeUnit.SECONDS);
// 这个操作符每隔指定的时间就从上游中取出一个事件发送给下游. 这里我们让它每隔2秒取一个事件给下游
Observable.zip(stringObservable, integerObservable, new BiFunction<String, Integer, String>() {
@Override
public String apply(String s, Integer integer) throws Exception {
return s + integer;
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("haha", "result = " + s);
}
});
方案二(从速度上控制):适当减慢发送事件的速度
Observable<String> stringObservable =Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("taoge");
}
}) .subscribeOn(Schedulers.io());
Observable<Integer> integerObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
for (int i = 0; ; i++) {
Thread.sleep(2000);
e.onNext(i);
}
}
}).subscribeOn(Schedulers.io());
Observable.zip(stringObservable, integerObservable, new BiFunction<String, Integer, String>() {
@Override
public String apply(String s, Integer integer) throws Exception {
return s + integer;
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("haha", "result = " + s);
}
});
Flowable
http://www.jianshu.com/p/9b1304435564
Demo地址: