Оператор switchMap () не отписывается от предыдущего запроса - PullRequest
2 голосов
/ 04 мая 2019

Я создал Observable, который испускает текст из edittext.Затем, используя оператор switchmap, я создаю сингл, который ищет совпадение в файле.

Здесь я подписываюсь:

compositeDisposable.add(getEditTextObservable(editText)
    .debounce(500, TimeUnit.MILLISECONDS)
    .map(String::toLowerCase)
    .filter(s -> !TextUtils.isEmpty(s))
    .switchMapSingle(s -> textCutter.getSearchResult(s))
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe()
);

Вот поиск:

public Single<List<TextCut>> getSearchResult(String searchRequest) {
    return Single.fromCallable(() -> textGen.getCutList(searchRequest));
}

В результате я получаю, что каждый запрос выполняется по очереди.Например, если я ввожу запрос «собака», а затем «кошка», в результате я получаю «собака» и «кошка». Хотя я ожидал получить только "кошку"

Например:
input : собака
"собака" в процессе ...
вход : кошка
выход : [результат 'собака']
"кошка" вprogess ...
output : [результат 'cat']

Что я ожидал получить:
ввод : собака
"собака" в процессе ...
ввод : кошка
"собака" отменена ...
"кошка" в проге ...
вывод : [результат 'кошки]]

1 Ответ

1 голос
/ 04 мая 2019

Протестировав отдельно оператор switchMapSingle, используя поток событий, аналогичный вашему, я не могу найти никаких проблем с оператором swtichMapSingle - он пропустит, когда он должен пропустить, и испустить, когда должен - я также пробовал различные способы потоков, но все соблюдают функциональность оператора. В другом месте должна быть проблема.

Выполнение тестового кода ( важная часть - начиная с момента отладки , комментарии добавлены для отображения ожидаемых результатов):

public static void main(String... args) {
    final AtomicInteger aInt = new AtomicInteger();
    final AtomicBoolean aBool = new AtomicBoolean(true);

    Observable.just(0)
            .map(i -> {
                final int i2 = i + aInt.incrementAndGet();
                // simulate interval events even every 200 millis, odds every 400 millis
                Thread.sleep(i2 % 2 == 0 ? 200 : 400);
                return i2;
            })
            .repeat()
            // skip all odd numbers
            .debounce(300, MILLISECONDS)
            .switchMapSingle(i3 ->
                    // toggle between 0 and 2 second delay - every 2 second delay dropped (every other even number)
                    Single.just(i3).delay(aBool.getAndSet(!aBool.get())? 0 : 2_000, MILLISECONDS))
            .subscribeOn(Schedulers.io())
            .observeOn(Schedulers.single())
            // expected out - every other even number i.e 2, 6, 10, 14 ..
            .subscribe(i4 -> System.out.println(String.format("Value : %d", i4)));

    try {
        Thread.sleep(60_000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

вывод:

Value : 2
Value : 6
Value : 10
Value : 14
Value : 18
Value : 22
Value : 26

Чтобы подтвердить при использовании flatMapSingle, что ни одно событие не пропущено, выход также соответствует ожидаемому - выбросы не по порядку будут выбросами, уменьшенными на switchMapSingle

Вывод с flatMapSingle:

Value : 2
Value : 6
Value : 10
Value : 4    // dropped with switch map single
Value : 14
Value : 8    // dropped with switch map single
Value : 18
Value : 12   // dropped with switch map single
...