Как работает switchMap в RxJava
Что проверяют
Понимаете ли вы разницу между операторами с внутренними потоками и что происходит с подпиской при отмене. Следом обычно просят сравнить switchMap с flatMap и concatMap и собрать живой поиск.
Как отвечать
switchMap превращает каждый элемент источника во внутренний Observable, но держит подписку только на последний. Как только приходит новый элемент, предыдущая внутренняя подписка отменяется через dispose(), и её результаты вниз по цепочке не попадут.
Сравнение:
flatMap: подписывается на все внутренние потоки параллельно, результаты перемешиваются, порядок не гарантирован;concatMap: обрабатывает внутренние потоки по одному, порядок сохраняется, но медленный запрос задерживает все следующие;switchMap: только актуальный запрос, устаревшие отменяются.
Типовой пример на Android это поиск по мере ввода: поток текста из поля, затем debounce(300, TimeUnit.MILLISECONDS), distinctUntilChanged(), switchMap { query -> api.search(query).subscribeOn(Schedulers.io()) } и observeOn(AndroidSchedulers.mainThread()). Retrofit с адаптером для RxJava 3 при dispose() отменяет вызов в OkHttp, то есть запрос реально обрывается.
Про завершение и ошибки: итоговый поток завершается, когда завершились и источник, и последний внутренний поток. Ошибка во внутреннем потоке по умолчанию завершает всю цепочку, для отложенной доставки ошибок есть switchMapDelayError. Для Single и Maybe есть switchMapSingle и switchMapMaybe. В корутинах аналог это flatMapLatest у Flow.
Где спотыкаются
Не обрабатывают ошибку внутри switchMap. Один таймаут поиска убивает весь поток ввода, и поиск молчит до пересоздания экрана. Нужен onErrorReturn или onErrorResumeNext на внутреннем потоке.
Применяют switchMap к операциям, которые нельзя отменять: сохранению, оплате, отправке формы. Повторное нажатие оборвёт предыдущий запрос, и неизвестно, дошёл ли он до сервера.
Считают, что отмена подписки останавливает любую работу. Если внутренний источник не поддерживает отмену, например произвольный блокирующий код в fromCallable, работа может дойти до конца, просто её результат выбросят.