Compose Snapshots
❓ После доклада меня много спрашивали, а зачем мне вообще знать про снапшоты? Где эти знания применить на практике?
💡 И на мой взгляд, в первую очередь их нужно знать, чтобы разобраться, а каким образом изменение State внутри Composable функции приводит к рекомпозиции?
✳️ Давайте сначала вспомним, что вообще такое Snapshot
Это механизм, используемый внутри Compose State и не только, для работы с множественными изолированными копиями состояния. Снапшоты также позволяют сделать безопасное изменение стейта конкурентно без блокировок. Можете думать про снапшоты как про транзакции в базах данных или как про ветки в git.
✳️ Причем тут снапшоты и рекомпозиция?
Все Composable дерево заворачивается в Snapshot, поэтому на самом деле изменение стейта не происходит глобально, а происходит внутри снапшота, поэтому снапшот может отследить каждое чтение и запись любого стейта внутри, так Compose понимает какие части экрана нужно перерисовать в дальнейшем.
✳️ Где снапшоты могут пригодиться на практике?
🟠 Если вдруг вы захотите написать свою либу поверх compose runtime
🟡 Для безопасного изменения стейта с нескольких потоков
🔵 Для создания своего изменяемого Stable типа, отслеживаемого Compose
🔵 Для всего, на что способно ваше воображение! Например, почему бы не работать с БД через Compose State? Что? Да! Это тоже возможно благодаря снапшотам.
Но самое крутое и полезное применение снапшотов я покажу в следующем посте, так что stay tuned💻
#Compose #Snapshots
Это механизм, используемый внутри Compose State и не только, для работы с множественными изолированными копиями состояния. Снапшоты также позволяют сделать безопасное изменение стейта конкурентно без блокировок. Можете думать про снапшоты как про транзакции в базах данных или как про ветки в git.
Все Composable дерево заворачивается в Snapshot, поэтому на самом деле изменение стейта не происходит глобально, а происходит внутри снапшота, поэтому снапшот может отследить каждое чтение и запись любого стейта внутри, так Compose понимает какие части экрана нужно перерисовать в дальнейшем.
private inline fun <T> composing(
composition: ControlledComposition,
modifiedValues: IdentityArraySet<Any>?,
block: () -> T
): T {
val snapshot = Snapshot.takeMutableSnapshot(
readObserverOf(composition), writeObserverOf(composition, modifiedValues)
)
try {
return snapshot.enter(block)
} finally {
applyAndCheck(snapshot)
}
}
Но самое крутое и полезное применение снапшотов я покажу в следующем посте, так что stay tuned
#Compose #Snapshots
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥9
This media is not supported in your browser
VIEW IN TELEGRAM
Compose withAnimation
В SwiftUI есть очень классная фича
Не справедливо, что такого механизма нет из коробки в Compose, и инженер из Google решил исправить это недоразумение. Он сделал свой аналог
Как это работает?
1. Создается пустой словарь состояний для анимации
2. Выполняется лямбда блок внутри Snapshot, в этой лямбде могут происходить изменения стейта
3. У Snapshot вызывается
4. Данные мапятся в другой тип, откуда достаются измененные значения
5. Уничтожается Snapshot, чтобы не допустить утечек памяти, при этом изменения не применяются глобально! «Все что произошло в снапшоте, остается в снапшоте»©
6. Анимируются значения
Если у вас есть еще идеи как можно применить снапшоты, делитесь своими мыслями в комментариях👇
#Compose #Snapshots #Animations
В SwiftUI есть очень классная фича
withAnimation
, позволяющая сделать анимацию вьюшки просто путем изменения состояния, а сама анимация произойдет как по волшебству.
@State private var showDetail = false
var body: some View {
VStack {
Button("Show details") {
withAnimation {
showDetail.toggle()
}
}
if showDetail {
Text("Details")
}
}
}
Не справедливо, что такого механизма нет из коробки в Compose, и инженер из Google решил исправить это недоразумение. Он сделал свой аналог
withAnimation
и реализовал это с помощью Snapshot API, про который мы говорили ранее.Как это работает?
1. Создается пустой словарь состояний для анимации
2. Выполняется лямбда блок внутри Snapshot, в этой лямбде могут происходить изменения стейта
3. У Snapshot вызывается
writeObserver
при каждой записи в State и заполняется информация для анимации4. Данные мапятся в другой тип, откуда достаются измененные значения
5. Уничтожается Snapshot, чтобы не допустить утечек памяти, при этом изменения не применяются глобально! «Все что произошло в снапшоте, остается в снапшоте»©
6. Анимируются значения
internal suspend fun withAnimation(
adapterRegistry: StateObjectAdapterRegistry,
animationSpec: AnimationSpec<Any?>,
block: () -> Unit
) {
val statesToAnimate = mutableMapOf<Any, StateObjectAdapter>() // 1
val snapshot = Snapshot.takeMutableSnapshot(
writeObserver = { changedState ->
statesToAnimate[changedState] = checkNotNull(adapterRegistry.getAdapterFor(changedState)) // 3
}
)
val targetValues = snapshot.enter {
block() // 2
buildTargetValues(statesToAnimate) // 4
}
snapshot.dispose() // 5
animateValues(targetValues, animationSpec) // 6
}
Если у вас есть еще идеи как можно применить снапшоты, делитесь своими мыслями в комментариях👇
#Compose #Snapshots #Animations
🔥10👍2