Как запустить эффект в Compose
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Запуск эффектов в Jetpack Compose
В Jetpack Compose эффекты (side effects) — это функции, которые позволяют выполнять действия, выходящие за рамки рекомпозиции, такие как подписки на потоки данных, анимации, одноразовые операции или взаимодействие с внешними API. Эффекты запускаются в ответ на изменения состояний и жизненного цикла компонентов.
Основные виды эффектов
1. LaunchedEffect — для корутин и асинхронных операций
Используется для запуска приостанавливаемых функций внутри Composable-функции. Автоматически отменяется при выходе из композиции или изменении ключей.
@Composable
fun TimerExample() {
var seconds by remember { mutableStateOf(0) }
LaunchedEffect(key1 = Unit) { // Запускается один раз при первом составлении
while (isActive) {
delay(1000)
seconds++
}
}
Text(text = "Прошло $seconds секунд")
}
2. DisposableEffect — для ресурсов с очисткой
Предназначен для эффектов, которые требуют очистки (dispose) при удалении из композиции или изменении ключей.
@Composable
fun SensorExample() {
val sensorManager = LocalContext.current.getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
DisposableEffect(key1 = sensor) {
val listener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent?) {
// Обработка данных сенсора
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}
sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL)
onDispose {
sensorManager.unregisterListener(listener) // Важно очищать ресурсы!
}
}
}
3. SideEffect — для не-композиционных операций
Запускается после каждой успешной рекомпозиции, без возможности отмены. Полезен для синхронизации с внешними системами.
@Composable
fun AnalyticsTracker(isScreenVisible: Boolean) {
val analytics = LocalAnalytics.current
SideEffect {
analytics.trackScreenVisibility(isScreenVisible) // Вызывается после каждой рекомпозиции
}
}
4. rememberUpdatedState — для захвата актуального значения
Позволяет эффекту использовать самое актуальное значение, даже если оно изменилось после запуска эффекта.
@Composable
fun DelayedAction(onAction: () -> Unit) {
val currentOnAction by rememberUpdatedState(newValue = onAction)
LaunchedEffect(key1 = Unit) {
delay(3000)
currentOnAction() // Будет использовать актуальный onAction, даже если он изменился
}
}
Практические паттерны использования
Запуск эффекта при изменении состояния:
@Composable
fun UserProfile(userId: String) {
var userData by remember { mutableStateOf<User?>(null) }
LaunchedEffect(key1 = userId) { // Перезапускается при изменении userId
userData = userRepository.fetchUser(userId)
}
// Отображение данных пользователя
}
Комбинирование нескольких эффектов:
@Composable
fun ComplexScreen(isActive: Boolean) {
// Эффект для подписки на данные
LaunchedEffect(key1 = isActive) {
if (isActive) {
dataFlow.collect { /* обработка данных */ }
}
}
// Эффект для анимации
val animatedValue by animateFloatAsState(
targetValue = if (isActive) 1f else 0f
)
// Эффект для логирования
SideEffect {
Log.d("ComplexScreen", "isActive changed to: $isActive")
}
}
Ключевые правила использования:
- Всегда указывайте ключи (key1, key2, ...) для контроля перезапуска эффекта
- Избегайте побочных эффектов в теле Composable-функции — они должны быть внутри специальных эффектов
- Очищайте ресурсы в
onDisposeдляDisposableEffect - Не изменяйте состояние непосредственно в
SideEffect— это может вызвать бесконечную рекомпозицию - Используйте
rememberCoroutineScopeдля запуска корутин вне эффектов:
@Composable
fun ButtonWithAction() {
val scope = rememberCoroutineScope()
Button(onClick = {
scope.launch {
// Асинхронная операция по клику
}
}) {
Text("Выполнить")
}
}
Выбор правильного эффекта
- LaunchedEffect: для асинхронных операций, которые нужно отменить
- DisposableEffect: для ресурсов, требующих очистки (подписки, слушатели)
- SideEffect: для синхронизации с внешними состояниями
- rememberCoroutineScope: для запуска корутин по событию (клик и т.д.)
Правильное использование эффектов обеспечивает предсказуемость, предотвращает утечки памяти и делает код более читаемым, разделяя логику рендеринга и побочные операции.