Как отобразить количество новых сообщений в списке чатов и как получить эти данные от сокета
Что проверяют
Умеете ли вы построить поток данных от сокета до списка на экране без гонок и рассинхрона. Счётчик кажется простым +1, но интервьюер ждёт разговора о переподключении, дублях и чтении с другого устройства. Следом спрашивают, что происходит со счётчиком, пока приложение в фоне.
Как отвечать
Опишите слои:
- соединение: WebSocket через OkHttp (
newWebSocketсWebSocketListener) или клиент Socket.IO, если сервер на нём. Живёт в синглтоне data-слоя, а не во ViewModel экрана, иначе каждый экран откроет своё соединение; - поток событий: колбэки оборачиваются в
callbackFlow, события парсятся в sealed-классы вродеNewMessageиChatRead; - источник правды: события пишутся в Room, у таблицы чатов есть поле
unreadCount. Лучше, когда сервер присылает актуальное значение счётчика, а не команду «прибавь один»: повторная доставка после реконнекта не удвоит цифру, а дубли сообщений отсекаются поmessageId; - UI: DAO отдаёт
Flow<List<ChatEntity>>, ViewModel делает из негоStateFlowчерезstateIn, экран на Compose собирает егоcollectAsStateWithLifecycleи рисуетBadgeс ограничением «99+». ВLazyColumnзадайтеkey = { it.id }, чтобы изменение одного чата не перерисовывало весь список; - синхронизация: после каждого подключения приложение запрашивает актуальные счётчики по REST, потому что за время обрыва события могли потеряться. При открытии чата уходит отметка о прочтении с id последнего сообщения, и сервер рассылает
ChatReadна все устройства.
В фоне сокет держать не нужно: система всё равно ограничит сеть, а о новых сообщениях сообщит push через FCM, после которого счётчики обновятся синхронизацией.
Где спотыкаются
Считают непрочитанные только на клиенте инкрементом. После реконнекта, повторной доставки и чтения с веба цифра расходится с реальностью.
Обновляют LiveData через setValue из потока сокета. Колбэки приходят не в главном потоке, и приложение падает с IllegalStateException; нужен postValue, а лучше Flow из Room.
Держат сокет открытым после ухода со всех экранов чата. Это расход батареи и лишние соединения на сервере, а в фоне система всё равно его оборвёт.