前言
上一篇文章,我们已经了解了RxJava的相关概念以及基础使用方式。这篇文章将会结合RxJava知识点与开发中遇到的实际场景进行讲解,让大家能够通过这些例子更好的理解与掌握RxJava的用法与思想
数据请求
这是一个完整的数据请求例子,从缓存、网络以及数据解析等。本例要实现的是若数据库有对应的数据则直接使用缓存的数据,否则再通过网络请求获取数据,并且完成解析与缓存等操作
1.创建网络请求Observable从网络获取数据
(1)Observable.create()调起网络请求获取数据
(2)map操作符将网络响应映射为数据实体
(3)doOnNext操作符将数据存储到数据库
2.创建数据库缓存读取Observable读取缓存
3.Observable.concat合并上述两个Observable
Observable net = Observable.create(new ObservableOnSubscribe<Response>() {
@Override
public void subscribe(ObservableEmitter<Response> e) throws Exception {
Request.Builder builder = new Request.Builder()
.url("http://gank.io/api/data/Android/10/1")
.get();
Request request = builder.build();
Call call = new OkHttpClient().newCall(request);
Response response = call.execute();
e.onNext(response);
}
}).map(new Function<Response, GankIOAndroidEntity>() {
@Override
public GankIOAndroidEntity apply(Response response) throws Exception {
ResponseBody body = response.body();
if(body!=null){
return JSON.parseObject(body.toString(),GankIOAndroidEntity.class);
}
return null;
}
}).doOnNext(new Consumer<GankIOAndroidEntity>() {
@Override
public void accept(GankIOAndroidEntity gankIOAndroidEntity) throws Exception {
saveDB();
}
});
Observable cache = Observable.create(new ObservableOnSubscribe<GankIOAndroidEntity>() {
@Override
public void subscribe(ObservableEmitter<GankIOAndroidEntity> e) throws Exception {
GankIOAndroidEntity entity = getFromDB();
if(entity!=null){
e.onNext(entity);
}else{
e.onComplete();
}
}
});
Observable.concat(cache,net)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<GankIOAndroidEntity>() {
@Override
public void accept(GankIOAndroidEntity gankIOAndroidEntity) throws Exception {
displayUI();
}
});
当然还有一种情况,就是进入页面时若有缓存先展示缓存,但不管是否有缓存都请求网络数据并更新缓存。咱们只需要修改一下cache对象即可,不管缓存查询结果如何,都执行net操作
Observable cache = Observable.create(new ObservableOnSubscribe<GankIOAndroidEntity>() {
@Override
public void subscribe(ObservableEmitter<GankIOAndroidEntity> e) throws Exception {
GankIOAndroidEntity entity = getFromDB();
if(entity!=null){
e.onNext(entity);
}
e.onComplete(); // 不管缓存查询结果如何,都执行net操作
}
});
网络请求嵌套
我想大家肯定都遇到过类似这样的情况,在某个接口请求完成后再进行下一个请求的调用。比如:先注册成功后再调用登陆接口、先上传头像再保存资料、先更改数据再查询数据等等例子
我们可以通过flatMap操作符来方便的实现上述的请求嵌套,摆脱天花乱坠的回调嵌套。复习一下flatMap的作用:FlatMap将一个发射数据的Observable变换为多个Observables,然后将它们发射的数据合并后放进一个单独的Observable
Observable.create(new ObservableOnSubscribe<CallBackEntity>() {
@Override
public void subscribe(ObservableEmitter<CallBackEntity> e) throws Exception {
RequestBody body = new FormBody.Builder()
.add("username","lee")
.add("password","lee")
.build();
Request.Builder builder = new Request.Builder()
.url("http://xxx/register")
.post(body);
Request request = builder.build();
Call call = new OkHttpClient().newCall(request);
Response response = call.execute();
CallBackEntity entity =
JSON.parseObject(response.body().toString(),CallBackEntity.class);
e.onNext(entity);
}
}).flatMap(new Function<CallBackEntity, ObservableSource<CallBackEntity>>() {
@Override
public ObservableSource<CallBackEntity> apply(CallBackEntity callBackEntity) throws Exception {
// register successful
if(callBackEntity.getCode() == 0){
return Observable.create(new ObservableOnSubscribe<CallBackEntity>() {
@Override
public void subscribe(ObservableEmitter<CallBackEntity> e) throws Exception {
RequestBody body = new FormBody.Builder()
.add("username","lee")
.add("password","lee")
.build();
Request.Builder builder = new Request.Builder()
.url("http://xxx/login")
.post(body);
Request request = builder.build();
Call call = new OkHttpClient().newCall(request);
Response response = call.execute();
CallBackEntity entity =
JSON.parseObject(response.body().toString(),CallBackEntity.class);
}
});
}
return null;
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<CallBackEntity>() {
@Override
public void accept(CallBackEntity callBackEntity) throws Exception {
displayUI();
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
// error
}
});
数据合并
某个页面的展示可能需要同时调用好多个接口来得到完整的数据,可以用zip合并数据
Observable data1 = Observable.create(subscibe1);
Observable data2 = Observable.create(subscibe2);
Observable.zip(data1, data2, new BiFunction() {
@Override
public Object apply(Data1 o, Data2 o2) throws Exception {
Data data = new Data(o,o2);
return data;
}
}).subscribe(new Consumer() {
@Override
public void accept(Object o) throws Exception {
displayUI();
}
});
按钮防点击
登陆按钮、发送验证码按钮等各种与接口请求或者逻辑操作关联按钮,防止多次点击造成的非预期效果
RxView.clicks(btn)
.throttleFirst(1, TimeUnit.SECONDS)
.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
}
});
复杂的数据变换
Observable.just(dbData)
.map(new Function<List<String>, Object>() {
@Override
public Object apply(List<String> strings) throws Exception {
return null;
}
})
.filter(new Predicate<Object>() {
@Override
public boolean test(Object o) throws Exception {
return false;
}
}).distinct(new Function<Object, Object>() {
@Override
public Object apply(Object o) throws Exception {
return null;
}
}).take(pageSize)
.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
}
});
按钮的增量监听
addTextChangedListener与setOnClickListener,相信大家都不陌生吧,不知道大家知道它们俩对于事件的监听有什么区别吗?不了解的同学我解释下,addTextChangedListener内部维护了一个集合存储设置的所有监听对象,当事件产生时会向这所有监听发送回调。而setOnClickListener内部存储了OnClickListener对象,用于保存设置的监听对象,也就是说只有一个。结果很明显,addTextChangedListener是增量监听,setOnClickListener是覆盖
那么有没有办法实现OnClickListener的增量监听呢?有的~
当然,类似的还有OnTouchListener、focusChanges、drags等等
Observable<Object> shareClick = RxView.clicks(textView).share();
Observable<MotionEvent> shareTouch = RxView.touches(textView).share();
shareClick.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
// listener1
}
});
shareClick.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
// listener2
}
});
获取验证码倒计时
verifyCodeObservable = RxView.clicks(mBt)
.throttleFirst(SECOND, TimeUnit.SECONDS)
.subscribeOn(AndroidSchedulers.mainThread())
.doOnNext(new Action1<Void>() {
@Override
public void call(Void aVoid) {
RxView.enabled(mBt).call(false);
}
});
verifyCodeObservable.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
Observable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
.take(SECOND)
.subscribe(new Observer<Long>() {
@Override
public void onCompleted() {
RxTextView.text(mBt).call("获取验证码");
RxView.enabled(mBt).call(true);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, e.toString());
}
@Override
public void onNext(Long aLong) {
RxTextView.text(mBt).call("剩余" + (SECOND - aLong) + "秒");
}
});
}
});
必填项/表单验证
Observable<CharSequence> ObservableName = RxTextView.textChanges(mEtPhone);
Observable<CharSequence> ObservablePassword = RxTextView.textChanges(mEtPassword);
Observable.combineLatest(ObservableName, ObservablePassword, new Func2<CharSequence, CharSequence, Boolean>() {
@Override
public Boolean call(CharSequence phone, CharSequence password) {
return isPhoneValid(phone.toString()) && isPasswordValid(password.toString());
}
}).subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
RxView.enabled(mBtLogin).call(aBoolean);
}
});
RxView.clicks(mBtLogin)
.throttleFirst(1, TimeUnit.SECONDS)
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
Toast.makeText(LoginActivity.this, "登录成功!" ,Toast.LENGTH_SHORT).show();
}
});
响应式SP
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
RxSharedPreference rxSharedPreference = RxSharedPreference.create(preferences);
Preferences<Boolean> choose = rxSharedPreference.getBoolean("choose",false);
RxCompoundButton.checkedChanges(checkBox)
.subscribe(rxSharedPreference.asAction());
RxJava各种扩展库
rx-preferences -使SharedPreferences支持RxJava
RxAndroid -RxJava的Android拓展
RxLifecycle -帮助使用了RxJava的安卓应用控制生命周期
RxBinding -安卓UI控件的RxJava绑定API
storio -支持RxJava的数据库
retrofit -支持RxJava的网络请求库
sqlbrite -支持RxJava的sqlite数据库
RxPermissions -RxJava实现的Android运行时权限控制
reark -RxJava architecture library for Android
frodo -Android Library for Logging RxJava Observables and Subscribers.
总结
没有做不到,只有想不到。加油~