Мое текущее приложение для Android позволяет пользователям удаленно искать контент.
Например, пользователю предоставляется EditText
который принимает их строки поиска и запускает удаленный вызов API, который возвращает результаты, соответствующие введенному тексту.
Хуже того, я просто добавляю TextWatcher
и запускаю вызов API каждый раз, onTextChanged
вызывается onTextChanged
. Это можно было бы улучшить, заставив пользователя ввести не менее N символов для поиска до первого вызова API.
Решение "Perfect" будет иметь следующие функции:
Как только пользователь начнет вводить строку поиска,
Периодически (каждые M миллисекунд) потребляется вся строка (строки). Запускайте вызов API каждый раз, когда истекает период, и текущий пользовательский ввод отличается от предыдущего пользовательского ввода.
[Возможно ли иметь динамический тайм-аут, связанный с длиной введенных текстов? например, в то время как текст "короткий", размер ответа API будет большим и займет больше времени для возврата и анализа; По мере увеличения текста поиска размер ответа API будет уменьшаться вместе с "потоком" и временем разбора]
Когда пользователь перезапускает ввод в поле EditText, перезапустите периодическое потребление текста.
Всякий раз, когда пользователь нажимает клавишу вызова "конечный" API кнопки "ENTER" и останавливает мониторинг ввода пользователя в поле 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 + "]");
}
});
Ни один из которых не дает мне условного фильтра, который объединяет введенную длину текста и значение тайм-аута.
Я также заменил debounce с помощью throttleLast и образец, из которого не было требуемого решения.
Возможно ли достичь моей требуемой функциональности?
ДИНАМИЧЕСКОЕ ВРЕМЯ
Допустимое решение будет соответствовать следующим трем сценариям
я). Пользователь хочет найти любое слово, начинающееся с "P",
II). Пользователь хочет найти любое слово, начинающееся с "Pneumo"
III). Пользователь хочет найти слово "Pneumonoultramicroscopicsilicovolcanoconiosis"
Во всех трех сценариях, как только пользователь наберет букву "P", я покажу счетчик производительности (однако на данный момент никакой вызов API не будет выполнен). Я хотел бы уравновесить необходимость предоставления обратной связи с поиском пользователей в рамках адаптивного пользовательского интерфейса, чтобы сделать "потерянные" API-вызовы по сети.
Если бы я мог полагаться на пользователя, вводящего его текст поиска, а затем нажав кнопку "Готово" (или "Enter"), я мог бы немедленно запустить окончательный вызов API.
Первый сценарий
Так как текст, введенный пользователем, коротким (например, длиной 1 символ). Мое значение тайм-аута будет иметь максимальное значение. Это дает пользователю возможность вводить дополнительные символы и сохраняет "потерянные API-вызовы".
Поскольку пользователь хочет выполнить поиск только буквы "P", как только истечет время ожидания Max, я буду выполнять вызов API и отображать результаты. Этот сценарий дает пользователю худший пользовательский опыт, так как ему нужно дождаться окончания моего динамического таймаута, а затем дождаться возврата и отображения ответа Большого API. Они не будут видеть результаты промежуточного поиска.
Сценарий два
Этот сценарий объединяет сценарий один, поскольку я понятия не имею, что пользователь будет искать (или конечную длину строк поиска), если они набирают все 6 символов "быстро", я могу выполнить один вызов API, однако медленнее они входят в 6 символы увеличат вероятность выполнения запущенных API-вызовов.
Этот сценарий дает пользователю улучшенный пользовательский интерфейс, так как ему нужно дождаться истечения времени ожидания Dynamic Timeout, однако у них есть шанс увидеть результаты промежуточного поиска. Ответы API будут меньше, чем сценарий один.
Сценарий три
Этот сценарий объединяет сценарии один и два, поскольку я понятия не имею, что пользователь будет искать (или конечную длину строк поиска), если они набирают все 45 символов "быстро", я могу выполнить один вызов API (возможно!), Однако медленнее они набирают 45 символов, что увеличит вероятность выполнения запущенных API-вызовов.
Я не привязан к какой-либо технологии, которая доставляет мое желаемое решение. Я считаю, что Rx - лучший подход, который я определил до сих пор.