Какие знаешь еще эффекты помимо DisposableEffect?
Комментарии (3)
Ответ сгенерирован нейросетью и может содержать ошибки
Эффекты в Compose: Beyond DisposableEffect
В Jetpack Compose эффекты — это функции, которые позволяют выполнять side-эффекты в рамках композиции. Помимо DisposableEffect, существует несколько других ключевых эффектов, каждый из которых решает определённые задачи. Вот основные из них:
1. LaunchedEffect
Запускает приостанавливаемую функцию (coroutine) внутри области видимости композиции. Автоматически отменяется при выходе из композиции или изменении ключей.
@Composable
fun TimerExample() {
var time by remember { mutableStateOf(0) }
LaunchedEffect(key1 = Unit) {
while (isActive) {
delay(1000)
time++
}
}
Text(text = "Прошло $time секунд")
}
2. SideEffect
Выполняет код при каждой успешной рекомпозиции. Используется для синхронизации состояния Compose с внешними системами, не поддерживающими наблюдаемые изменения.
@Composable
fun AnalyticsTracker(screenName: String) {
SideEffect {
// Отправка аналитики при каждой рекомпозиции
Analytics.logScreenView(screenName)
}
}
3. rememberCoroutineScope
Создает CoroutineScope, привязанную к области видимости композиции. Отменяется при выходе из композиции. Полезен для запуска корутин из callback-ов (например, onClick).
@Composable
fun CoroutineExample() {
val scope = rememberCoroutineScope()
var data by remember { mutableStateOf<String?>(null) }
Button(onClick = {
scope.launch {
data = fetchData()
}
}) {
Text("Загрузить данные")
}
}
4. rememberUpdatedState
Создает ссылку на значение, которое может изменяться со временем, но не вызывает рестарт эффекта при изменении. Полезен для длительных операций, где нужно использовать актуальное значение.
@Composable
fun RememberUpdatedExample(onTimeout: () -> Unit) {
val currentOnTimeout by rememberUpdatedState(newValue = onTimeout)
LaunchedEffect(key1 = Unit) {
delay(3000)
currentOnTimeout() // Всегда вызовет актуальный callback
}
}
5. produceState
Преобразует внешние источники данных в State Compose. Автоматически запускает и останавливает producer-корутину.
@Composable
fun ProduceStateExample(userId: String): State<Result<User>> {
return produceState(initialValue = Result.Loading, userId) {
val user = userRepository.getUser(userId)
value = Result.Success(user)
}
}
6. derivedStateOf
Создает производное состояние, которое вычисляется на основе других состояний. Оптимизирует рекомпозиции, вычисляясь только при изменении зависимостей.
@Composable
fun DerivedStateExample(items: List<String>) {
val scrollState = rememberLazyListState()
val showButton by remember {
derivedStateOf {
scrollState.firstVisibleItemIndex > 0
}
}
if (showButton) {
Button(onClick = { /* Действие */ }) {
Text("Вверх")
}
}
}
7. snapshotFlow
Преобразует State Compose в Flow. Позволяет реагировать на изменения состояния в корутинах или других частях приложения.
@Composable
fun SnapshotFlowExample(searchQuery: String) {
val scope = rememberCoroutineScope()
LaunchedEffect(key1 = searchQuery) {
snapshotFlow { searchQuery }
.debounce(300)
.distinctUntilChanged()
.collect { query ->
scope.launch {
viewModel.search(query)
}
}
}
}
Ключевые различия между эффектами
- LaunchedEffect vs DisposableEffect: Оба имеют ключи и вызывают dispose, но LaunchedEffect предназначен для корутин, а DisposableEffect — для любых ресурсов.
- SideEffect vs DisposableEffect: SideEffect не имеет dispose-логики и выполняется при каждой рекомпозиции, в то время как DisposableEffect управляет жизненным циклом ресурсов.
- produceState vs LaunchedEffect: produceState специализирован на преобразовании данных в State, в то время как LaunchedEffect более универсален.
Практические рекомендации
- Используйте LaunchedEffect для одноразовых асинхронных операций при изменении ключей
- Применяйте DisposableEffect для управления подписками, слушателями и другими ресурсами
- Выбирайте SideEffect для синхронизации с внешними системами без состояния
- Оптимизируйте с derivedStateOf вычисления, зависящие от нескольких состояний
- Используйте snapshotFlow для сложных реактивных цепочек на основе состояния Compose
Понимание этих эффектов позволяет эффективно управлять side-эффектами, ресурсами и асинхронными операциями в Compose, создавая отзывчивые и эффективные UI.