我当前的 Android 应用程序允许用户远程搜索内容。
例如,用户会看到一个EditText
接受他们的搜索字符串并触发远程 API 调用,返回与输入文本匹配的结果。
更糟糕的情况是我TextWatcher
每次调用时只需添加一个并触发一个 API 调用onTextChanged
。这可以通过强制用户在进行第一次 API 调用之前输入至少 N 个字符进行搜索来改进。
“完美”解决方案将具有以下特点:-
一旦用户开始输入搜索字符串
定期(每 M 毫秒)消耗输入的整个字符串。每次期限到期且当前用户输入与之前的用户输入不同时触发 API 调用。
[是否可以有与输入文本长度相关的动态超时?例如,当文本“短”时,API 响应大小会很大,返回和解析需要更长的时间;随着搜索文本变长,API 响应大小将随着“飞行”和解析时间而减少]
当用户重新开始在 EditText 字段中输入时,重新开始定期使用文本。
每当用户按下 ENTER 键触发“最终”API 调用,并停止监视用户对 EditText 字段的输入。
设置用户在触发 API 调用之前必须输入的最小文本长度,但将此最小长度与覆盖的超时值结合起来,以便当用户希望搜索“短”文本字符串时,他们可以。
我确信 RxJava 和/或 RxBindings 可以支持上述要求,但是到目前为止我还没有实现可行的解决方案。
我的尝试包括
private PublishSubject<String> publishSubject;
publishSubject = PublishSubject.create();
publishSubject.filter(text -> text.length() > 2)
.debounce(300, TimeUnit.MILLISECONDS)
.toFlowable(BackpressureStrategy.LATEST)
.subscribe(new Consumer<String>() {
@Override
public void accept(final String s) throws Exception {
Log.d(TAG, "accept() called with: s = [" + s + "]");
}
});
mEditText.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) {
publishSubject.onNext(s.toString());
}
@Override
public void afterTextChanged(final Editable s) {
}
});
这与 RxBinding
RxTextView.textChanges(mEditText)
.debounce(500, TimeUnit.MILLISECONDS)
.subscribe(new Consumer<CharSequence>(){
@Override
public void accept(final CharSequence charSequence) throws Exception {
Log.d(TAG, "accept() called with: charSequence = [" + charSequence + "]");
}
});
两者都没有给我一个结合输入文本长度和超时值的条件过滤器。
我还用throttleLast 和sample 替换了debounce,两者都没有提供所需的解决方案。
是否有可能实现我所需的功能?
动态超时
可接受的解决方案将应对以下三种情况
一世)。用户希望搜索以“P”开头的任何单词
ii)。用户希望搜索以“Pneumo”开头的任何单词
三)。用户希望搜索词“Pneumonoultramicroscopicsilicovolcanoconiosis”
在所有三种情况下,只要用户键入字母“P”,我就会显示一个进度微调器(但是此时不会执行任何 API 调用)。我想在响应式 UI 中为用户提供搜索反馈与通过网络进行“浪费”API 调用之间取得平衡。
如果我可以依靠用户输入他们的搜索文本然后单击“完成”(或“Enter”)键,我可以立即启动最终的 API 调用。
情景一
由于用户输入的文本长度较短(例如 1 个字符长),我的超时值将处于最大值,这使用户有机会输入其他字符并节省“浪费的 API 调用”。
由于用户希望单独搜索字母“P”,因此一旦 Max Timeout 到期,我将执行 API 调用并显示结果。这种情况给用户带来了最糟糕的用户体验,因为他们必须等待我的动态超时到期,然后等待返回并显示大型 API 响应。他们不会看到任何中间搜索结果。
方案二
这个场景结合了场景一,因为我不知道用户要搜索什么(或搜索字符串的最终长度)如果他们“快速”键入所有 6 个字符我可以执行一个 API 调用,但是他们输入的速度越慢 6字符会增加执行浪费的 API 调用的机会。
这种情况为用户提供了改进的用户体验,因为他们必须等待我的动态超时到期,但是他们确实有机会看到中间搜索结果。API 响应将小于方案一。
场景三
这个场景结合了场景一和场景二,因为我不知道用户将要搜索什么(或搜索字符串的最终长度),如果他们“快速”键入所有 45 个字符我可以执行一个 API 调用(也许!),但是他们键入 45 个字符的速度较慢将增加执行浪费的 API 调用的机会。
我不依赖于提供我想要的解决方案的任何技术。我相信 Rx 是迄今为止我发现的最好的方法。