Ответ вслух Senior Compose: состояние и side-effects обновлено

Где хранить состояние в Compose-приложении

Вопрос

Как ты решаешь, где хранить состояние: в composable, в state holder или во ViewModel?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Я разделяю бизнес-состояние и UI-состояние. Данные экрана, загрузка, ошибки и всё, что зависит от репозиториев, живут во ViewModel и отдаются как StateFlow<UiState: она переживает поворот, тестируется без UI и может использовать SavedStateHandle.

Что должно прозвучать в ответе

  • Бизнес-данные и логика экрана во ViewModel, наружу StateFlow

  • UI-элементы состояния в composable через remember/rememberSaveable

  • Сложная UI-логика в классе state holder с remember-функцией

  • Подъём до ближайшего общего предка

  • Ввод пользователя должен пережить поворот и смерть процесса

  • Один источник правды, без дублирования

Что могут спросить следом

  • Почему не держать всё во ViewModel?
  • Как протестировать state holder?

Разбор

Я разделяю бизнес-состояние и UI-состояние. Данные экрана, загрузка, ошибки и всё, что зависит от репозиториев, живут во ViewModel и отдаются как StateFlow<UiState>: она переживает поворот, тестируется без UI и может использовать SavedStateHandle. Чисто визуальное состояние, например раскрыт ли элемент, позиция скролла или фокус, держу в composable через remember или rememberSaveable, если его надо пережить поворот. Если UI-логики становится много, например форма с валидацией и несколькими полями, выношу её в обычный класс state holder и создаю его через свою функцию rememberFormState(), как это сделано у rememberLazyListState. Состояние поднимаю до ближайшего общего предка, не выше, и слежу, чтобы у каждого значения был один владелец, иначе появляются рассинхроны. Всё во ViewModel не держу: тогда она знает о деталях UI и растёт без меры.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.