Как будет происходить обновление списка чатов при получении нового сообщения
Что проверяют
Умеете ли вы спроектировать поток данных от сети до экрана с одним источником правды, а не просто «повесить LiveData». Следом спрашивают, что будет, если сообщение пришло, пока приложение в фоне, или пришло дважды.
Как отвечать
Опишите путь сообщения по слоям:
- доставка: пока приложение на экране, держится WebSocket (например, через OkHttp), в фоне приходит data-сообщение FCM. После переподключения клиент догружает пропущенное по курсору последней синхронизации;
- запись: репозиторий в одной транзакции Room сохраняет сообщение и обновляет строку чата: текст и время последнего сообщения, счётчик непрочитанных. Дубли отсекаются по id сообщения;
- чтение: DAO отдаёт
Flow<List<ChatPreview>>сORDER BY last_message_at DESC. Room сам переизлучает список при изменении таблицы, вручную ничего дёргать не нужно; - ViewModel: превращает поток в
StateFlowчерезstateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList()); - UI: сбор с учётом жизненного цикла,
repeatOnLifecycle(Lifecycle.State.STARTED)илиcollectAsStateWithLifecycle()в Compose. В RecyclerView нуженListAdapterсDiffUtil, вLazyColumnстабильныйkeyпо id чата. Тогда чат анимированно поднимается наверх, а весь список не перерисовывается.
Если чатов тысячи, подключается Paging 3: PagingSource из Room сам инвалидируется при изменении таблицы. Продумайте прокрутку: если пользователь смотрит середину списка, не прыгайте к началу.
Где спотыкаются
Вызывают notifyDataSetChanged(). Список перерисовывается целиком, пропадают анимации, а на длинном списке это заметно дёргается.
Держат список только в памяти ViewModel и дописывают туда сообщения из сокета. Появляются два источника правды, данные теряются при смерти процесса, а пуш и сокет расходятся.
Не думают о дублях и порядке. Одно сообщение может прийти и по WebSocket, и через FCM, а после переподключения порядок доставки не совпадает с порядком отправки, поэтому сортируют по серверному времени или порядковому номеру.