一 .基本用法
(1).Rxjava是一个用于处理异步和基于事件编程的Java库.
(2).Rxjava原理就是类似于观察者模式
-
观察者模式面向的需求是:A 对象(观察者)对 B 对象(被观察者)的某种变化高度敏感,需要在 B 变化的一瞬间做出反应。举个例子,新闻里喜闻乐见的警察抓小偷,警察需要在小偷伸手作案的时候实施抓捕。在这个例子里,警察是观察者,小偷是被观察者,警察需要时刻盯着小偷的一举一动,才能保证不会漏过任何瞬间。
-
程序的观察者模式和这种真正的『观察』略有不同,观察者不需要时刻盯着被观察者(例如 A 不需要每过 2ms 就检查一次 B 的状态),而是采用注册(Register)或者称为订阅(Subscribe)的方式,告诉被观察者:我需要你的某某状态,你要在它变化的时候通知我。
-
Android 开发中一个比较典型的例子是点击监听器 OnClickListener 。对设置 OnClickListener 来说, View 是被观察者, OnClickListener 是观察者,二者通过 setOnClickListener() 方法达成订阅关系。订阅之后用户点击按钮的瞬间,Android Framework 就会将点击事件发送给已经注册的 OnClickListener 。采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。
RxJava 有四个基本概念:Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。
//.create创建了一个Observable<String> 的可发射事件.
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) {
e.onNext("1"); //可以多次调用
e.onNext("1"); //可以多次调用
e.onComplete();
// e.onError(new Exception());
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
在 RxJava 的 subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber 再使用。所以如果你只想使用基本功能,选择 Observer 和 Subscriber 是完全一样的。它们的区别对于使用者来说主要有两点。
A:onStart():这是 Subscriber 增加的方法。
B: unsubscribe(): 这是 Subscriber 所实现的另一个接口 Subscription 的方法,用于取消订阅, 一般在这个方法调用前,可以使用 isUnsubscribed() 先判断一下状态。 unsubscribe() 这个方法很重要,因为在 subscribe() 之后, Observable 会持有 Subscriber 的引用,这个引用如果不能及时被释放,将有内存泄露的风险。所以最好保持一个原则:要在不再使用的时候尽快在合适的地方(例如 onPause() onStop() 等方法中)调用 unsubscribe() 来解除引用关系,以避免内存泄露的发生。
(3).操作符( map,floatmap,filter ,take ,takelast,distinct,skip变换操作符)
- just操作符创建Observable被观察者对象
Observable.just(1,2,3,4,5).subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.i(TAG,"onCompleted:");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
Log.i(TAG,"onNext:"+integer);//执行5次
}
});
- map操作符----将原Observable发射出来的数据转换为另外一种类型的数据
Observable.just("666").map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
return Integer.parseInt(s);
}
}).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
- floatmap操作符---作用类似于map又比map强大,map是单纯的数据类型的转换,而flapMap可以将原数转换成新的Observables,再将这些Observables的数据顺序缓存到一个新的队列中,在统一发射出来
List<AccountInfoBean> infoBeans=new ArrayList<>();
infoBeans.add(new AccountInfoBean());
infoBeans.add(new AccountInfoBean());
infoBeans.add(new AccountInfoBean());
Observable.just(infoBeans).flatMap(new Function<List<AccountInfoBean>, ObservableSource<AccountInfoBean>>() {
@Override
public ObservableSource<AccountInfoBean> apply(List<AccountInfoBean> beanList) throws Exception {
//把beanList中的每个对象转换成Observable<AccountInfoBean>
return Observable.fromIterable(beanList);
}
}).subscribe(new Consumer<AccountInfoBean>() {
@Override
public void accept(AccountInfoBean accountInfoBean) throws Exception {
System.out.println("xxx");//infoBeans中有3个元素,会执行3次
}
});
- filter操作符----对发射的数据做一个限制,只有满足条件的数据才会被发射
//对发射的数据做一个限制,只有满足条件的数据才会被发射
Observable.just("hello","Rxjava","Nice to meet you").filter(new Function<String, Boolean>() {
@Override
public Boolean apply(String s) {
return s.length()>5;
}
}).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onNext(String s) {
Log.i("TAG","filter过滤后的数据:"+s.toString());
}
});
- distinct操作符----过滤掉重复项
Observable.just("hello","hello","hello","Rxjava","Rxjava","Nice to meet you").filter(new Function<String, Boolean>() {
@Override
public Boolean apply(String s) {
return s.length()>5;
}
}).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onNext(String s) {
Log.i("TAG","distinct去除重复之后的数据:"+s.toString());
}
});
- Skip操作符----发射数据时忽略前N项数据(skpiLast忽略后N项数据)
Observable.just("hello","Rxjava","Nice to meet you").skip(2).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onNext(String s) {
Log.i("TAG","Skip之后的数据:"+s.toString());
}
});
- take操作符----只发射前N项的数据(takeLast与take想反,只取最后N项数据)
Observable.just("hello","Rxjava","Nice to meet you").take(2).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onNext(String s) {
Log.i("TAG","Take之后的数据:"+s.toString());
}
});
另外还有一些其他的操作符 range,Interval,empty,error等(www.jianshu.com/p/eceb6b31d…
二.线程调度Scheduler
(1).subscribeOn(Schedulers.io()) 或者observeOn(AndroidSchedulers.mainThread())
Observable.just(1, 2, 3, 4)
.subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
(2). Rxjava通过flatMap操作符解决回调地狱问题(OkHttp会导致回调地狱,无法切换线程)
api.requestFirstData()
.flatMap(data1 -> api.requestSecondData(data1.getId()))
.flatMap(data2 -> api.requestThirdData(data2.getToken()))
.subscribe(
data3 -> {
// 处理最终数据
},
throwable -> {
// 处理错误,这里不管是哪个环节出错,都会走到这里
}
);
//HttpResult<UserInfoBody> =====>Observable<HttpResult<List<HotBean>>>
HttpRetrofit.apiService.getUserInfo().flatMap(object:Function<HttpResult<UserInfoBody>,Observable<HttpResult<List<HotBean>>>>{
override fun apply(response: HttpResult<UserInfoBody>): Observable<HttpResult<List<HotBean>>>? {
return HttpRetrofit.apiService.getHotKeyListTest(response.data?.username?:"");
}
})
(3). kotlin协程,解决地狱回调问题。(第二接口依赖于第一个接口的参数)
// 注意:在真实开发过程中,MainScope作用域用的非常常用
MainScope().launch(){ // 注意:此协程块默认是在UI线程中启动协程
// 下面的代码看起来会以同步的方式一行行执行(异步代码同步获取结果)
val token = apiService.getToken() // 网络请求:IO线程,获取用户token
val user = apiService.getUser(token)// 网络请求:IO线程,获取用户信息
nameTv.text = user.name // 更新 UI:主线程,展示用户名
val articleList = apiService.getArticleList(user.id)// 网络请求:IO线程,根据用户id获取用户的文章集合哦
articleTv.text = "用户${user.name}的文章页数是:${articleList.size}页" // 更新 UI:主线程
}
(4).zip操作符解决并发执行问题
Observable<Boolean> observable1 = Observable.create(new ObservableOnSubscribe<Boolean>() {
@Override
public void subscribe(ObservableEmitter<Boolean> emitter) throws Exception {
// 模拟网络请求1
Thread.sleep(1000);
return "Data from API 1";
}
}).subscribeOn(Schedulers.io());// 指定在IO线程执行请求
Observable<Boolean> observable2 = Observable.create(new ObservableOnSubscribe<Boolean>() {
@Override
public void subscribe(ObservableEmitter<Boolean> emitter) throws Exception {
// 模拟网络请求2
Thread.sleep(800);
return "Data from API 2";
}
}).subscribeOn(Schedulers.io());// 指定在IO线程执行请求
Observable.zip(observable1,observable2, (result1, result2) -> {
//模拟收到result1和result2结果不为null
CombineResult combinedResult=new CombineResult();
if(result1!=null&&result2!=null){
combinedResult.result1=result1;
combinedResult.result2=result2;
return combinedResult;
}
return null;
})
.observeOn(AndroidSchedulers.mainThread()) // 在 UI 线程接收结果
.subscribe(combinedResult -> {
// 处理组合后的结果
if(combinedResult!=null&&combinedResult.result1!=null&&combinedResult2!=null){
//更新UI
}
});