Для чего нужны side effects в Jetpack Compose
Что проверяют
Понимаете ли вы, что composable-функция может вызываться много раз и в любой момент, поэтому побочные действия в её теле недопустимы.
Как отвечать
Composable-функция описывает интерфейс и может быть вызвана при каждой рекомпозиции, а её выполнение может быть прервано или пропущено. Значит запускать оттуда напрямую сетевой запрос, показ сообщения или подписку нельзя: они выполнятся неизвестное число раз.
Эффекты дают контролируемое место для таких действий:
- LaunchedEffect(key): запускает корутину при входе в композицию и перезапускает при смене ключа, отменяя предыдущую. Загрузка данных, показ снекбара, анимация по событию;
- DisposableEffect(key): для того, что нужно освободить. Возвращает
onDispose, где снимается слушатель или подписка; - SideEffect: выполняется после каждой успешной рекомпозиции. Для передачи состояния в объекты вне Compose, например в аналитику;
- rememberCoroutineScope: область для запуска корутины из обработчика события, а не при композиции;
- rememberUpdatedState: чтобы длительный эффект видел свежее значение, не перезапускаясь;
- produceState и snapshotFlow: мосты между обычным состоянием, потоками и состоянием Compose.
Главное правило про ключи: ключ определяет, когда эффект перезапустится. Ключ Unit означает «один раз за жизнь композиции», меняющийся объект вместо идентификатора приводит к перезапуску на каждой рекомпозиции.
Где спотыкаются
Пишут вызов репозитория прямо в теле composable-функции.
Передают в ключ нестабильный объект и получают бесконечный перезапуск.
Используют LaunchedEffect там, где нужен обработчик нажатия, то есть rememberCoroutineScope.
Забывают onDispose и оставляют висящие подписки.