美文网首页
RxJava实际应用案例

RxJava实际应用案例

作者: 小甜李子 | 来源:发表于2018-03-26 12:13 被阅读0次

    前言

    上一篇文章,我们已经了解了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.

    总结

    没有做不到,只有想不到。加油~

    相关文章

      网友评论

          本文标题:RxJava实际应用案例

          本文链接:https://www.haomeiwen.com/subject/ntxrcftx.html