1、功能防抖
- 用户在规定时间内触发多次该功能,仅会响应第一次该功能
- RxView.clicks源码分析
eg:短时间内连续点击按钮
public static void throttleFirst() {
Button button = null;
RxView.clicks(button)
.throttleFirst(1, TimeUnit.SECONDS)
.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
//跳转
}
});
}
2、联想搜索优化
![]()
public static void search() {
EditText editText = null;
RxTextView.textChanges(editText)
.debounce(1, TimeUnit.SECONDS)
.skip(1)
.subscribe(new Consumer<CharSequence>() {
@Override
public void accept(CharSequence charSequence) throws Exception {
//开始搜索
}
});
}
3、联合判断
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="请填写姓名"
/>
<EditText
android:id="@+id/age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="请填写年龄"
/>
<EditText
android:id="@+id/job"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="请填写职业"
/>
<Button
android:id="@+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="提交"
android:enabled="false"
/>
</LinearLayout>
Observable<CharSequence> nameObservable = RxTextView.textChanges(name).skip(1);
Observable<CharSequence> ageObservable = RxTextView.textChanges(age).skip(1);
Observable<CharSequence> jobObservable = RxTextView.textChanges(job).skip(1);
/*
* 通过combineLatest()合并事件 & 联合判断
**/
Observable.combineLatest(nameObservable,ageObservable,jobObservable,new Function3<CharSequence, CharSequence, CharSequence,Boolean>() {
@Override
public Boolean apply(@NonNull CharSequence name, @NonNull CharSequence age, @NonNull CharSequence job) throws Exception {
//1. 姓名
boolean isUserNameValid = !TextUtils.isEmpty(name)
// 2. 年龄信息
boolean isUserAgeValid = !TextUtils.isEmpty(age);
// 3. 职业信息
boolean isUserJobValid = !TextUtils.isEmpty(job) ;
return isUserNameValid && isUserAgeValid && isUserJobValid;
}
}).subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean s) throws Exception {
Log.e(TAG, "提交按钮是否可点击: " + s);
list.setEnabled(s);
}
});
4、数据源合并
/ 用于存放最终展示的数据
String result = "数据源来自 = " ;
/*
* 设置第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 );
result += value + "+";
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
// 接收合并事件后,统一展示
@Override
public void onComplete() {
Log.d(TAG, "获取数据完成");
Log.d(TAG, result );
}
});
5、网络/缓存策略
// 该2变量用于模拟内存缓存 & 磁盘缓存中的数据
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("从网络中获取数据");
// 此处仅作网络请求的模拟
/*
* 通过concat() 和 firstElement()操作符实现缓存功能
**/
// 1. 通过concat()合并memory、disk、network 3个被观察者的事件(即检查内存缓存、磁盘缓存 & 发送网络请求)
// 并将它们按顺序串联成队列
Observable.concat(memory, disk, network)
// 2. 通过firstElement(),从串联队列中取出并发送第1个有效事件(Next事件),即依次判断检查memory、disk、network
.firstElement()
// 即本例的逻辑为:
// a. firstElement()取出第1个事件 = memory,即先判断内存缓存中有无数据缓存;由于memoryCache = null,即内存缓存中无数据,所以发送结束事件(视为无效事件)
// b. firstElement()继续取出第2个事件 = disk,即判断磁盘缓存中有无数据缓存:由于diskCache ≠ null,即磁盘缓存中有数据,所以发送Next事件(有效事件)
// c. 即firstElement()已发出第1个有效事件(disk事件),所以停止判断。
// 3. 观察者订阅
.subscribe(new Consumer<String>() {
@Override
public void accept( String s) throws Exception {
Log.d(TAG,"最终获取的数据来源 = "+ s);
}
});
6、轮询器
Disposable mDisposable;
//开启轮询
public void autoLoop() {
if (mDisposable == null || mDisposable.isDisposed()) {
Observable.interval(0, 5, TimeUnit.SECONDS)
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
}
});
}
}
//关闭轮询
public void stopLoop() {
if (mDisposable != null && !mDisposable.isDisposed()) {
mDisposable.dispose();
mDisposable = null;
}
}
7、定时器
//一段时间之后再做一些事情
public void timer() {
Observable.timer(5, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
}
});
}
8、倒计时
public static void countDown(final int count) {
Observable.intervalRange(0, count, 0, 1, TimeUnit.SECONDS)
.map(new Function<Long, Long>() {
@Override
public Long apply(Long aLong) throws Exception {
return count - aLong;
}
})
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe");
}
@Override
public void onNext(Long value) {
Log.d(TAG, "onNext: value = " + value);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete");
}
});
}