RxJava2的线程控制和操作符
Rx线程控制
Rx的链式调用:
这里利用String代替耗时的网络操作
Observable.just("我是网络请求操作")
// 被观察者线程 即onNext操作线程
.subscribeOn(Schedulers.io())
// 观察者线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Logger.d(s);
textview.setText(s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Logger.d(throwable);
}
});
subscribeOn(Schedulers) 和 observeOn(Schedulers) 来指定被观察者和观察者操作线程 Schedulers 有如下几种
Schedulers | 介绍 | 线程池大小 |
---|---|---|
Schedulers.io() | 通常用于网络,读写文件等io密集型的操作 | 无上限线程池 |
Schedulers.computation() | CPU计算密集型的操作(计算操作) | CPU 核心数 |
Schedulers.newThread() | 常规创建新线程 | |
AndroidSchedulers.mainThread() | Android主线程(RxAndroid 提供的) |
Rx 常用操作符
Rx的操作符非常多 要看文档来慢慢学习积累 先介绍几种常用的
创建操作符
create
defer
from
just
Timer
等等这些就是创建操作符
变换操作符 用于数据转换操作
buffer
flatMap
map
scan
groupBy
window
map
实现字符串转换数字
String num = "123";
String str = "我不是数字";
Observable.just(num).map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
//使用str转换会出异常 则在 onError中收到异常
return Integer.parseInt(s);
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
mMsg.setText(integer + "");
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Logger.d(throwable);
}
});
日志:
D/PRETTYLOGGER: ║ Thread: main
D/PRETTYLOGGER: ║ 123
flatMap 应用
需求有2个网络操作相互依赖 比如 登录操作A 可以拿到用户头像 请求头像操作B 来显示缓存头像
Observable.just("用户名和密码")
.flatMap(new Function<String, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(String s) throws Exception {
//A 网络操作 获取UserInfo
User user = ...
return Observable.just(user.getAvatar());
}
})
.flatMap(new Function<String, ObservableSource<Bitmap>>() {
@Override
public ObservableSource<Bitmap> apply(String url) throws Exception {
//B 通过url获取Bitmap
Bitmap avatar = ImageLoad.with(url);
return Observable.just(avatar);
}
})
//指定转换过程的线程
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Bitmap>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Bitmap bm) {
imageView.setImageBitmap(bm);
}
@Override
public void onError(Throwable e) {
Logger.d(e);
}
@Override
public void onComplete() {
Logger.d("onComplete");
}
});
丫! 代码怎么这么长 还不如原始的操作方式 A 的回调中再使用 B 。 其实不然,这只是在学习理解操作符的过程,后期这些学习会为我们带来更加简洁的使用方式
过滤操作符
filter
Observable.just("123456我")
.filter(new Predicate<String>() {
@Override
public boolean test(String s) throws Exception {
//类似校验操作 不满足条件不会继续传输
return s.contains("我");
}
})
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Logger.d(s);
}
});
日志: 123456我 ,onComplete
如果发送123456 则 最终直接 onComplete
Debounce
操作符会过滤掉发射速率过快的数据项(官方文档)。
解决频繁请求数据的需求
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
for (int i = 1; i < 5; i++) {
emitter.onNext(i + "");
// 模拟产生过快发送
Thread.sleep(i * 100);
}
emitter.onComplete();
}
}) //定义 速度过滤 超过此时长的可以发送出去
.debounce(300, TimeUnit.MILLISECONDS)
//数据校验器
.filter(new Predicate<String>() {
@Override
public boolean test(String s) throws Exception {
return !TextUtils.isEmpty(s);
}
})
//数据转换器具
.flatMap(new Function<String, ObservableSource<List<String>>>() {
@Override
public ObservableSource<List<String>> apply(String s) throws Exception {
List<String> list = new ArrayList<>();
list.add(s);
list.add("服务器列表数据1");
list.add("服务器列表数据2");
list.add("服务器列表数据3");
return Observable.just(list);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<String>>() {
@Override
public void onSubscribe(Disposable d) {
Logger.d("onSubscribe");
}
@Override
public void onNext(List<String> value) {
Logger.d("onNext:" + value);
}
@Override
public void onError(Throwable e) {
Logger.d("onError:" + e);
}
@Override
public void onComplete() {
Logger.d("onComplete");
}
});
switchMap 和 flatMap
官方文档说明是:
RxJava还实现了 switchMap 操作符。它和 flatMap 很像,除了一点:当原始Observable发射 一个新的数据(Observable)时,它将取消订阅并停止监视产生执之前那个数据的 Observable,只监视当前这一个。
这样去理解 发送A请求又发送了B请求,我们期望得到B的结果,然而由于A在服务器阻塞了,B先返回,紧接着A也返回了,这时候展示了A的结果。(常见的search接口) 这时候需要用到 switchMap