ViewModel нужно получать через ViewModelStore, а не создавать обычным remember. Для Android-состояния обычно используют collectAsStateWithLifecycle.
Выявление ошибок в экране, реализованном с помощью Jetpack Compose
ViewModel нужно получать через ViewModelStore, а не создавать обычным remember. Для Android-состояния обычно используют collectAsStateWithLifecycle.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Задача: проанализировать код экрана, написанного на Jetpack Compose, и найти потенциальные проблемы в его реализации.
@Composable
fun MyScreen() {
val screenViewModel = remember { MyViewModel() }
val uiState by screenViewModel.state.collectAsState()
MyComposableItem(
name = uiState.name,
onButtonClick = { screenViewModel.onAction() }
)
}
В данном примере создаётся ViewModel, собирается состояние через collectAsState, а полученные данные передаются в дочерний composable. Требуется определить, какие недостатки могут присутствовать в таком подходе (например, неправильное управление жизненным циклом ViewModel, отсутствие обработки ошибок, неэффективные пересоздания и т.п.).
Ответ
ViewModel нужно получать через ViewModelStore, а не создавать обычным remember. Для Android-состояния обычно используют collectAsStateWithLifecycle.
@Composable
fun MyScreen(screenViewModel: MyViewModel = viewModel()) {
val uiState by screenViewModel.state.collectAsStateWithLifecycle()
MyComposableItem(
name = uiState.name,
onButtonClick = { screenViewModel.onAction() }
)
}
Потребуются Compose-интеграции lifecycle; при Hilt вместо viewModel() используется hiltViewModel().
remember действительно сохраняет объект между рекомпозициями, поэтому утверждение «ViewModel создаётся на каждой рекомпозиции» неверно. Проблема в другом: объект не управляется ViewModelStore, не получает штатное сохранение при смене конфигурации и очистку владельцем. По этому фрагменту нельзя доказать отсутствие Loading/Error в модели: это проверяется отдельно.
Источник: developer.android.com.