Как реализовать логику поиска с задержкой на корутинах при вводе текста в TextField в Android
Что проверяют
Умеете ли вы связать ввод в Compose, ViewModel и Flow так, чтобы поиск не шёл на каждую букву, а устаревшие запросы отменялись. Следом обычно спрашивают, почему нельзя дебаунсить само значение поля и как это протестировать.
Как отвечать
Раз речь о TextField, это Jetpack Compose. Каркас:
- текст поля: хранится как состояние и обновляется синхронно на каждое нажатие, например
MutableStateFlow<String>воViewModel. Значение для самого поля через задержку не проходит; - поток запросов: к этому потоку применяются
debounce(300),distinctUntilChanged()и фильтр слишком коротких строк. Пустой запрос сразу очищает результаты без похода в сеть; - отмена:
flatMapLatestилиmapLatestотменяет предыдущий поиск при новом тексте. Suspend-функции Retrofit реагируют на отмену корутины и обрывают HTTP-запрос; - ошибки:
catchставится внутриflatMapLatestвокруг одного запроса. Иначе первое исключение завершит весь поток, и поиск перестанет работать до пересоздания экрана; - состояние UI:
sealed interfaceсIdle,Loading,Success,Error, затемstateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), ...), а в ComposecollectAsStateWithLifecycle().
Без операторов Flow то же делается через Job: searchJob?.cancel(), затем viewModelScope.launch { delay(300); search(q) }. Покажите это, если спросят, что происходит внутри debounce. Учтите, что debounce и flatMapLatest могут потребовать @OptIn, так как помечены как preview или experimental API.
Для тестов: runTest с виртуальным временем, advanceTimeBy(299) и проверка, что запроса не было, затем ещё миллисекунда и runCurrent(). Эмиссии удобно собирать через Turbine.
Где спотыкаются
Пропускают значение поля через debounce и отдают его обратно в TextField. Курсор прыгает, буквы теряются, ввод ощутимо тормозит.
Используют SharingStarted.Lazily или GlobalScope. Поток живёт дольше экрана и продолжает ходить в сеть в фоне.
Не отменяют предыдущий запрос. Ответ на «ко» приходит позже ответа на «кот» и перезаписывает правильные результаты.