2023
찰스의 안드로이드
컨퍼런스
📸 Snapshot System
•컴포즈에서 두 번째로 깊은 계층
•State의 구현체
•리컴포지션의 뼈대
Slide 7
Slide 7 text
2023
찰스의 안드로이드
컨퍼런스
이걸 왜 알아야 해?
•내부 개념인 만큼 컴포즈를 사용한다고 알아야 할 필요는 없다.
•컴포즈 런타임 구성으로만 쓰이기엔 아까운 기술이고, 대부분 public api로
구현돼 있어서 컴포즈 내부에 관심이 있다면 한 번쯤 봐볼 가치는 있다.
•이해하고 있으면 컴포즈의 상태 시스템을 자유자제로 다룰 수 있다.
Slide 8
Slide 8 text
2023
찰스의 안드로이드
컨퍼런스
1. What is Snapshot System?
Slide 9
Slide 9 text
2023
찰스의 안드로이드
컨퍼런스
📸 Snapshot System 컨셉
컴포지션은 특정 순서에 구애받지 않고 무작위 병렬로 실행된다.
→ 하나의 State에 여러 컴포지션이 동시에 접근할 수 있으며, 동시성 문제에 빠질 수 있음
Slide 10
Slide 10 text
2023
찰스의 안드로이드
컨퍼런스
📸 Snapshot System 컨셉
💡 모든 State 연산을 고립되게 진행하자!
컴포지션은 특정 순서에 구애받지 않고 무작위 병렬로 실행된다.
→ 하나의 State에 여러 컴포지션이 동시에 접근할 수 있으며, 동시성 문제에 빠질 수 있음
Slide 11
Slide 11 text
class StringPrinter {
private var value: String? = null
fun delayedPrint(value: String, delay: Long = 1000L) {
this.value = value
Thread.sleep(delay)
println(this.value)
}
}
Slide 12
Slide 12 text
fun main() {
val stringPrinter = StringPrinter()
thread { stringPrinter.delayedPrint("A") }
thread { stringPrinter.delayedPrint("B") }
}
Slide 13
Slide 13 text
fun main() {
val stringPrinter = StringPrinter()
thread { stringPrinter.delayedPrint("A") }
thread { stringPrinter.delayedPrint("B") }
}
// result: B, B
Slide 14
Slide 14 text
class StringPrinter {
private val value = ThreadLocal()
fun delayedPrint(value: String, delay: Long = 1000L) {
this.value.set(value)
Thread.sleep(delay)
println(this.value.get())
}
}
// result: A, B
Slide 15
Slide 15 text
class StringPrinter {
private val value = ThreadLocal()
fun delayedPrint(value: String, delay: Long = 1000L) {
this.value.set(value)
Thread.sleep(delay)
println(this.value.get())
}
}
// result: A, B
Snapshot
Slide 16
Slide 16 text
class StringPrinter {
private val value = ThreadLocal()
fun delayedPrint(value: String, delay: Long = 1000L) {
this.value.set(value)
Thread.sleep(delay)
println(this.value.get())
}
}
// result: A, B
Snapshot
“Snapshot System”
class StringPrinter {
private val value = ThreadLocal()
fun delayedPrint(value: String, delay: Long = 1000L) {
this.value.set(value)
Thread.sleep(delay)
println(this.value.get())
}
}
`
StateObject
StateRecord
Slide 23
Slide 23 text
val state = mutableStateOf(0)
state.value = 1
state.value = 2
state.value = 3
`
StateObject
StateRecord
// ୶ ੋ ࢚క чਸ ۨਵ۽ ࠂਗ
fun redo() {
if (currentFrame + 1 in frames.indices) {
target!!.restoreFrom(frames[++currentFrame])
}
}
Slide 41
Slide 41 text
2023
찰스의 안드로이드
컨퍼런스
Undo/Redo 시스템
1. 상태가 변경될 때마다 새로운 상태 값 저장
2. Undo 요청 시 이전 값으로 상태 복원
3. Redo 요청 시 다음 값으로 상태 복원
Slide 42
Slide 42 text
2023
찰스의 안드로이드
컨퍼런스
지금까지 만든 Undo/Redo 시스템
1. saveFrame(): 현재 프레임의 상태 값(StateRecord) 저장
2. track(): 추적할 상태(StateObject) 지정
3. undo(): 이전 프레임으로 상태 값(StateRecord) 복원
4. redo(): 다음 프레임으로 상태 값(StateRecord) 복원
Slide 43
Slide 43 text
2023
찰스의 안드로이드
컨퍼런스
이제 만들 Undo/Redo 시스템
1. saveFrame() 호출 시점
2. 과거 프레임에서 신규 프레임을 저장했을 때 프레임 처리 정책
Slide 44
Slide 44 text
2023
찰스의 안드로이드
컨퍼런스
saveFrame() 호출 시점
• 추적 중인 상태(StateObject)에 값(StateRecord)이 작성됐을 때 🙆
• undo()와 redo()로 상태 값(StateRecord)이 복원됐을 때 🙅