深入理解RxJava编程思想( 三 )


防抖+网络嵌套
我们先了解什么是抖动?
假如我有个,写一个自动化脚本来实现2s之内点击20次,那我就得请求20次网络,这样是很过分的,这就是抖动;如果我2s之内还是点击20次,可我只响应你一次,这种情况就是没有抖动 。我们要做的事情就是防止抖动 。
Rx家族成员有、RxJS、…,里面就有防抖的功能 。
通过上面的查询我们得到了项目分类数据和项目列表数据,如果我们想通过项目id来查询项目列表数据呢?这时候我们就需要进行网络嵌套,如果我们用传统的网络嵌套,那么会造成代码堆叠 。(负面教程,嵌套的太厉害了)
/*** RxBinding防抖动TODO网络嵌套*/@SuppressLint("CheckResult")public void antiShakeActon() {//对哪个控件防抖动?Button bt_anti_shake = findViewById(R.id.bt_anti_shake);RxView.clicks(bt_anti_shake).throttleFirst(2000, TimeUnit.MICROSECONDS)//2秒钟之内,响应一次.subscribe(new Consumer() {@Overridepublic void accept(Object o) throws Exception {api.getProject()//查询主数据.compose(DownloadActivity.rxud()).subscribe(new Consumer() {@Overridepublic void accept(ProjectBean projectBean) throws Exception {for (ProjectBean.DataBean dataBean : projectBean.getData()) {api.getProjectItem(1, dataBean.getId()) //查询Item数据.compose(DownloadActivity.rxud()).subscribe(new Consumer() {@Overridepublic void accept(ProjectItemBean projectItemBean) throws Exception {Log.d(TAG, "accept: " + projectItemBean);}});}}});}});}
这样,虽然我们实现了通过项目ID查询列表数据的功能,但是我们发现,如果我们嵌套层级太多,那我们的代码会形成一个阶梯状的局势,这样的代码是很不好看的,而且如果有问题,我们排查起来十分困难 。难道没有其他办法了吗?不不不,相信我们Rx爸爸,早已为我们铺好了道路 。
通过里面的就能愉快地解决网络嵌套的问题 。
示意图:
这个示意图的意思就是:可以自己分发多个数据给下面,终点就得到发的多个数据 。
熟悉了的原理后,我们用代码实现:
/*** TODO 功能防抖 + 网络嵌套 (解决嵌套问题) flatMap*/@SuppressLint("CheckResult")public void antiShakeActonUpdate() {Button bt_anti_shake = findViewById(R.id.bt_anti_shake);RxView.clicks(bt_anti_shake).throttleFirst(2000, TimeUnit.MICROSECONDS)//我只给下面切换异步线程.observeOn(Schedulers.io()).flatMap(new Function() {@Overridepublic ObservableSource apply(Object o) throws Exception {return api.getProject(); //主数据}}).flatMap(new Function>() {@Overridepublic ObservableSource apply(ProjectBean projectBean) throws Exception {return Observable.fromIterable(projectBean.getData());//我自己搞一个发射器,发送多次}}).flatMap(new Function>() {@Overridepublic ObservableSource apply(ProjectBean.DataBean dataBean) throws Exception {return api.getProjectItem(1, dataBean.getId());//Item数据}}).observeOn(AndroidSchedulers.mainThread())//给下面切换主线程.subscribe(new Consumer() {@Overridepublic void accept(ProjectItemBean projectItemBean) throws Exception {Log.d(TAG, "accept-------->: " + projectItemBean);textView.setText(projectItemBean.toString());}});}
运用
*需求:*1.请求服务器注册操作*2.注册完成之后,更新注册UI*3.马上去登录服务器操作*4.登录完成之后,更新登录的UI
现在我们有这样一个需求,首先我们分开写:
/*** TODO 方式一分开写* @param view*/@SuppressLint("CheckResult")public void request(View view) {// 1.请求服务器注册操作// 2.注册完成之后,更新注册UIMyRetrofit.createRetrofit().create(IRequestNetwork.class).registerAction(new RegisterRequest()).compose(DownloadActivity.rxud()).subscribe(new Consumer