Как отправлять запросы для поиска
Что проверяют
Вопрос не про то, как вызвать Retrofit, а про поиск по мере ввода: как не слать запрос на каждую букву, как отменить устаревший и не показать ответ на старую строку поверх нового. Следом обычно спрашивают, где живёт эта логика и что будет при повороте экрана.
Как отвечать
Актуальный стек: Kotlin, корутины, Retrofit с suspend-функциями (или Ktor), логика в ViewModel.
- API:
@GET("search") suspend fun search(@Query("q") q: String, @Query("page") page: Int): SearchResponse. Никакихenqueueи колбэков, отмена корутины отменяет и HTTP-вызов; - поток ввода: текст поля идёт в
MutableStateFlow<String>, дальшеdebounce(300),map { it.trim() },filter { it.length >= 2 },distinctUntilChanged(),flatMapLatest { q -> flow { emit(repo.search(q)) } }. ИменноflatMapLatestотменяет прежний запрос при новой строке, и ответы не приходят вразнобой; - состояние: результат превращается в
UiState(загрузка, данные, пусто, ошибка) черезstateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), ...). ViewModel переживает поворот, запрос не повторяется; - ошибки:
catchвнутриflatMapLatest, а не на всём потоке, иначе первая сетевая ошибка завершит поиск насовсем.IOExceptionпоказываем как «нет сети»,HttpExceptionразбираем по коду; - пагинация: длинная выдача через Paging 3,
PagingSourceполучает запрос и номер страницы,cachedIn(viewModelScope)держит загруженное.
Дополнительно: таймауты и HTTP-кеш в OkHttpClient, недавние запросы в Room, текст запроса в SavedStateHandle, чтобы он пережил смерть процесса.
Где спотыкаются
Шлют запрос на каждое изменение текста без debounce: десятки вызовов на одно слово и лишняя нагрузка на бэкенд.
Используют flatMapMerge или запускают новую корутину на каждый символ. Старый медленный ответ приходит последним и перетирает результат для актуальной строки.
Делают запрос прямо из Activity или Fragment. При повороте он уходит заново, а колбэк может прийти в уже уничтоженный экран.