В чем разница между LaunchedEffect и DisposableEffect?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между LaunchedEffect и DisposableEffect
Оба эффекта являются частью Compose Side-Effect системы и предназначены для выполнения операций вне потока композиции UI, но решают разные задачи и имеют различные жизненные циклы.
Ключевое концептуальное различие
LaunchedEffect предназначен для запуска корутин (приостанавливающих операций), которые должны выполняться в рамках жизненного цикла composable-функции. Он автоматически отменяет корутину при выходе из композиции.
DisposableEffect предназначен для подписки на внешние ресурсы или наблюдаемые объекты, требующие явного освобождения (dispose). Он выполняет cleanup-логику при уничтожении или рекомпозиции с измененными ключами.
LaunchedEffect: для асинхронных операций
@Composable
fun TimerExample() {
var seconds by remember { mutableStateOf(0) }
// Запускаем корутину при входе в композицию
LaunchedEffect(Unit) {
while (true) {
delay(1000)
seconds++
}
}
Text(text = "Прошло секунд: $seconds")
}
Характеристики LaunchedEffect:
- Автоматический запуск корутины при входе в композицию
- Автоматическая отмена при выходе из композиции
- Принимает ключи (keys) - при их изменении предыдущая корутина отменяется и запускается новая
- Не имеет блока cleanup - отмена корутины происходит автоматически
- Идеален для: анимаций, загрузки данных, таймеров, обработки событий жизненного цикла
DisposableEffect: для ресурсов с cleanup
@Composable
fun SensorExample() {
val context = LocalContext.current
var sensorValue by remember { mutableStateOf(0f) }
DisposableEffect(Unit) {
// Инициализация ресурса
val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
val listener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
sensorValue = event.values[0]
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}
sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL)
// Блок cleanup - выполнится при уничтожении
onDispose {
sensorManager.unregisterListener(listener)
}
}
Text(text = "Значение сенсора: $sensorValue")
}
Характеристики DisposableEffect:
- Требует блока
onDisposeдля очистки ресурсов - Выполняется синхронно (не запускает корутины автоматически)
- Ключи определяют переинициализацию - при изменении ключей выполняется cleanup и эффект запускается заново
- Идеален для: подписок на BroadcastReceiver, слушателей событий, регистрации в системных сервисах, кастомных очисток
Сравнительная таблица
| Аспект | LaunchedEffect | DisposableEffect |
|---|---|---|
| Основное назначение | Запуск корутин | Управление ресурсами с cleanup |
| Автоматическая отмена | Да (для корутин) | Нет (требует явного onDispose) |
| Возвращаемое значение | Нет | DisposableEffectResult |
| Корутины | Запускает автоматически | Не запускает автоматически |
| Cleanup логика | Нет | Обязательный блок onDispose |
| Использование с ключами | Перезапуск при изменении | Переинициализация при изменении |
Практические сценарии использования
Когда использовать LaunchedEffect:
- Загрузка данных из сети/БД при монтировании компонента
- Запуск анимаций или таймеров
- Реакция на изменения состояния с асинхронными операциями
- Навигация после завершения асинхронной операции
Когда использовать DisposableEffect:
- Регистрация BroadcastReceiver
- Подписка на Flow/LiveData из ViewModel
- Работа с системными сервисами Android (сенсоры, локация)
- Кастомные подписки на события, требующие отписки
- Управление жизненным циклом сторонних библиотек
Важные нюансы
- Ключи (keys) у обоих эффектов работают одинаково - эффект перезапускается при изменении любого ключа
- Не использовать для UI-логики - оба эффекта выполняются вне потока композиции
- DisposableEffect может содержать корутины, но их нужно отменять в
onDispose:
DisposableEffect(key1) {
val job = CoroutineScope(Dispatchers.IO).launch {
// асинхронная работа
}
onDispose {
job.cancel() // Явная отмена корутины
// Другая очистка
}
}
Оба эффекта являются важными инструментами для работы с побочными эффектами в Compose, и их правильное применение критично для создания надежных, эффективных приложений без утечек ресурсов.