← Назад к вопросам

Как Compose понимает что state поменялся

2.0 Middle🔥 141 комментариев
#UI и вёрстка#Архитектура и паттерны

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как Compose определяет изменения состояния

Compose использует систему отслеживания состояния на основе snapshot (снимков) для обнаружения изменений. Это фундаментально отличается от реактивных систем на базе Observable/Listener, так как Compose не полагается на явные вызовы уведомлений, а автоматически отслеживает чтение состояния во время композиции.

Ключевые механизмы отслеживания

1. Snapshot система

Compose использует mutableStateOf() или другие State объекты, которые обертывают значения в SnapshotMutableState. Когда вы меняете значение через .value или прямое присваивание, система снимков фиксирует изменение:

// Создание отслеживаемого состояния
var count by mutableStateOf(0)

// Изменение - автоматически помечается в текущем Snapshot
count++ // или count = 10

2. Чтение во время композиции

Compose запоминает, какие State объекты были прочитаны внутри @Composable функции во время ее выполнения:

@Composable
fun Counter() {
    val count = remember { mutableStateOf(0) }
    
    // Compose запоминает, что эта композиция читает count.value
    Text(text = "Count: ${count.value}")
    
    Button(onClick = { count.value++ }) {
        Text("Increment")
    }
}

Когда выполняется Text(text = "Count: ${count.value}"), система регистрирует, что эта конкретная композиция зависит от count.

3. Изменение и инвалидация

При изменении значения:

  • Система помечает снимок состояния (snapshot) как измененный
  • Все composable функции, которые читали это состояние, помечаются как недействительные (invalidated)
  • Compose планирует их перекомпозицию
// Упрощенный процесс
val state = mutableStateOf(0)

// 1. Чтение в композиции - регистрация зависимости
val currentValue = state.value // Запоминается связь

// 2. Изменение
state.value = 1 // Помечается в snapshot

// 3. Система находит все зарегистрированные зависимости
// 4. Планирует перекомпозицию зависимых composable функций

Техническая реализация

Структура State объектов

// Упрощенный вид mutableStateOf
fun <T> mutableStateOf(value: T): MutableState<T> {
    return SnapshotMutableStateImpl(value)
}

// SnapshotMutableStateImpl хранит:
// - current value
// - policy (structuralEqualityPolicy, referentialEqualityPolicy)
// - список наблюдателей (читателей)

Политики сравнения

Compose использует разные стратегии для определения "изменения":

// 1. Референциальное равенство (по умолчанию)
var data by mutableStateOf<List<String>>(emptyList())
// Перекомпозиция только если новый объект !== старому

// 2. Структурное равенство
var data by mutableStateOf(emptyList<String>(), structuralEqualityPolicy())
// Перекомпозиция при !equals() сравнении

Глобальный Snapshot

Система работает через глобальную систему снимков:

// Изменения происходят внутри apply-блоков
Snapshot.withMutableSnapshot {
    state1.value = 10
    state2.value = 20
    // Все изменения видны одновременно
}

Пример полного цикла

@Composable
fun UserProfile(userId: Int) {
    // 1. remember + mutableStateOf создает отслеживаемое состояние
    val userData = remember(userId) { 
        mutableStateOf<User?>(null) 
    }
    
    // 2. Чтение в композиции - регистрация зависимости
    val userName = userData.value?.name ?: "Loading..."
    
    // 3. Display зависит от userData.value
    Text(text = userName)
    
    // 4. При изменении (например, из ViewModel)
    LaunchedEffect(userId) {
        userData.value = fetchUser(userId) // Изменение!
        // Автоматически вызывает перекомпозицию Text
    }
}

Критически важные аспекты

  1. Автоматическое отслеживание - Вам не нужно явно подписываться или отписываться
  2. Гранулярная перекомпозиция - Перекомпозируются только те composable, которые реально читают измененное состояние
  3. Умное сравнение - Compose может пропускать перекомпозицию если входные параметры не изменились
  4. Потокобезопасность - Система snapshot корректно работает в многопоточных средах

Диагностика проблем

Для отладки используйте модификаторы:

Text(
    text = "Count: $count",
    modifier = Modifier.drawWithCache {
        // Помогает понять, когда происходит перекомпозиция
        onDrawWithContent {
            println("Recomposing Text!")
            drawContent()
        }
    }
)

Compose эффективно отслеживает изменения благодаря глубокой интеграции системы snapshot с runtime Kotlin и компилятором, что позволяет достичь высокой производительности при минимальном ручном управлении состоянием.

Как Compose понимает что state поменялся | PrepBro