我们时常有会碰到这种情形:在一个EditText中,并且针对该文本:当我输入时,一个响应将被自动触发,从而打印出我输入的文本,或者现在这样的反应被称为一个API的调用。所以,如果我们输入的每一个字符做出的这种反应将是一种浪费,因为我们只想需要知道最后一个输入,这意味着在我停止打字的时候它应该只触发一个call!
传统解决方法
我用一个定时器,并且安排它在afterTextChanged()方法延时1000毫秒后调用run()方法
//Java
Timer timer = new Timer();
final TextView textView = (TextView) findViewById(R.id.textView);
final EditText editText = (EditText) findViewById(R.id.editText);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(final CharSequence s, int start, int before,
int count) {
if (timer != null)
timer.cancel();
}
@Override
public void afterTextChanged(final Editable s) {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText("Output : " + editText.getText());
}
});
}
}, 1000);
}
});
使用RxJava
1.创建一个observable
2.添加Debounce operator,1000毫秒(1秒)的延迟
3.订阅它
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(final Subscriber<? super String> subscriber) {
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
}
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
subscriber.onNext(s.toString());
}
@Override
public void afterTextChanged(final Editable s) {
}
});
}
})
.debounce(1000, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(final String s) {
textView.setText("Output : " + s);
}
});
更少的样板——RxBindings!
我们可以使用RxBindings——这是RxJava结合了Android的UI组件的API。
RxTextView.afterTextChangeEvents(editText)
.debounce(1000,TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(tvChangeEvent -> {
textView.setText("Output : " + tvChangeEvent.view()
.getText());
});