1、简介:上篇文章中已经介绍了每种组合操作符的简单使用了,相信已经感受到功能的强大之处了,但上面的每个例子都是简单的更能演示,下面我们看看RxJava在实际开发中是如何大显神通的吧。
- 获取数据
一般我们在获取服务器数据时,拿到数据后会做缓存处理,所以当再次请求时会先查看缓存或磁盘中是否有相关的内容,即查询顺序为:
- 查询内存中是否有缓存
- 查询硬盘上是否有缓存
- 从服务器获取
代码演示:
String memoryCache = null; String diskCache = "从磁盘缓存中获取数据"; /* * 设置第1个Observable:检查内存缓存是否有该数据的缓存 **/ Observable<String> memory = Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> emitter) throws Exception { // 先判断内存缓存有无数据 if (memoryCache != null) { // 若有该数据,则发送 emitter.onNext(memoryCache); } else { // 若无该数据,则直接发送结束事件 emitter.onComplete(); } } }); /* * 设置第2个Observable:检查磁盘缓存是否有该数据的缓存 **/ Observable<String> disk = Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> emitter) throws Exception { // 先判断磁盘缓存有无数据 if (diskCache != null) { // 若有该数据,则发送 emitter.onNext(diskCache); } else { // 若无该数据,则直接发送结束事件 emitter.onComplete(); } } }); /* * 设置第3个Observable:通过网络获取数据 **/ Observable<String> network = Observable.just("从网络中获取数据"); // 1. 通过concat()合并memory、disk、network 3个被观察者的事件(即检查内存缓存、磁盘缓存 & 发送网络请求) Observable.concat(memory, disk, network) // 2. 通过firstElement(),从串联队列中取出并发送第1个有效事件(Next事件),即依次判断检查memory、disk、network .firstElement() // 3. 观察者订阅 .subscribe(new Consumer<String>() { @Override public void accept( String s) throws Exception { Log.d(TAG,"最终获取的数据来源 = "+ s); } });
- 合并数据
使用场景:像两个数据源获取数据然后一起显示
代码示例:
/* * 设置第1个Observable:通过网络获取数据 * 此处仅作网络请求的模拟 **/ Observable<String> network = Observable.just("网络"); /* * 设置第2个Observable:通过本地文件获取数据 * 此处仅作本地文件请求的模拟 **/ Observable<String> file = Observable.just("本地文件"); /* * 通过merge()合并事件 & 同时发送事件 **/ Observable.merge(network, file) .subscribe(new Observer<String>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(String value) { Log.d(TAG, "数据源有: "+ value ); } @Override public void onError(Throwable e) { Log.d(TAG, "对Error事件作出响应"); } // 接收合并事件后,统一展示 @Override public void onComplete() { Log.d(TAG, "获取数据完成"); } });
也可使用zip 对两者进行合并
Observable.zip(network, file, new BiFunction<String, String, String>() { @Override public String apply(String string, String s) throws Exception { return string +"="+s; } }).subscribe(new Consumer<String>() { @Override public void accept(String s) throws Exception { Log.e("zip=====",s); } });
- 联合判断
例如:只有当姓名/年龄/职业都输入才可以提交
/* * 步骤2:为每个EditText设置被观察者,用于发送监听事件 * 说明: * 1. 此处采用了RxBinding:RxTextView.textChanges(name) = 对对控件数据变更进行监听(功能类似TextWatcher),需要引入依赖:compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0' * 2. 传入EditText控件,点击任1个EditText撰写时,都会发送数据事件 = Function3()的返回值(下面会详细说明) * 3. 采用skip(1)原因:跳过 一开始EditText无任何输入时的空值 **/ Observable<CharSequence> nameObservable = RxTextView.textChanges(name).skip(1); Observable<CharSequence> ageObservable = RxTextView.textChanges(age).skip(1); Observable<CharSequence> jobObservable = RxTextView.textChanges(job).skip(1); /* * 步骤3:通过combineLatest()合并事件 & 联合判断 **/ Observable.combineLatest(nameObservable,ageObservable,jobObservable,new Function3<CharSequence, CharSequence, CharSequence,Boolean>() { @Override public Boolean apply(@NonNull CharSequence charSequence, @NonNull CharSequence charSequence2, @NonNull CharSequence charSequence3) throws Exception { /* * 步骤4:规定表单信息输入不能为空 **/ // 1. 姓名信息 boolean isUserNameValid = !TextUtils.isEmpty(name.getText()) ; // 除了设置为空,也可设置长度限制 // boolean isUserNameValid = !TextUtils.isEmpty(name.getText()) && (name.getText().toString().length() > 2 && name.getText().toString().length() < 9); // 2. 年龄信息 boolean isUserAgeValid = !TextUtils.isEmpty(age.getText()); // 3. 职业信息 boolean isUserJobValid = !TextUtils.isEmpty(job.getText()) ; /* * 步骤5:返回信息 = 联合判断,即3个信息同时已填写,"提交按钮"才可点击 **/ return isUserNameValid && isUserAgeValid && isUserJobValid; } }).subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean s) throws Exception { /* * 步骤6:返回结果 & 设置按钮可点击样式 **/ Log.e(TAG, "提交按钮是否可点击: "+s); list.setEnabled(s); } });