초기 Composition 과정
새로운 composition이 생성될 때마다 setContent()가 호출되며, 이 호출은 초기 상태의 composition 프로세스를 시작하기 위해 상위 composition에 위임된다.
override fun setContent(content: @Composable () -> Unit) {
this.composable = content
parent.composeInitial(this, composable)
}
초기 composition을 수행하는 로직은 항상 recomposer에 의존하게 된다.
이는 하위 composition은 루트 composition에 도달할 때까지 지속적으로 composeInitial 호출을 상위 요소에 위임하기 때문이다.
따라서 parent.composeInitial(composition, content)에 대한 호출은 recomposer.composeInitial로 변환될 수 있으며 초기 composition을 구축하기 위해 몇 가지 중요한 작업을 수행한다.
- 모든 State 객체의 현재 값을 스냅샷으로 취한다. 스냅샷은 가변적이지만 동시성에 대한 안정성을 가지고 있기 때문에 다른 State 스냅샷에 영향을 주지 않고 안전하게 수정될 수 있다.
- 이 가변적인 스냅샷의 State 값은 snapshot.enter(block: () → T)를 호출할 때 전달된 블록 내에서만 수정될 수 있다.
- 스냅샷이 변경될 때 Recomposer는 변경된 state 객체가 읽거나 쓰는 작업이 발생할 때 recomposition 한다.
- composition.composeContent(content)와 같은 블록에 snapshot.enter(block) 블록을 전달함으로써 스냅샷에 드어가며 composition이 실제로 일어나는 곳이다.
- Composition 프로세스는 Composer에게 위임되며, 작업이 완료되면 객체의 모든 변경 사항은 현재 State 스냅샷에만 적용되므로 snapshot.apply()를 통해 변경 사항이 전파된다.
이러한 대략적인 순서에 따 초기 composition이 실행된다.
이제 Composer에게 위임된 실제 composition 과정을 살펴보자.
- Composition은 이미 작업 중인 경우 새로 시작할 수 없다.
- 보류 중인 invalidation이 있다면 Composer가 유지하는 invalidation 목록으로 복사하여 RecomposeScope의 invalidation을 기다린다.
- Composition 작업의 실행 상태를 알리기 위해 isComposing 플래그를 true로 변경한다.
- Composition이 시작되며 startRoot()를 호출하면 composition의 루트 그룹을 시작하고, 필요한 필드와 구조를 초기화한다.
- 슬롯테이블로부터 content 그룹을 시작하기 위해 startGroup을 호출한다.
- content 람다식을 호출 하여 변경사항을 방출한다.
- 슬롯데이블로부터 그룹을 끝내기 위해 endGroup을 호출한다.
- endRoot()를 호출하여 composition을 끝낸다.
- Composition 작업의 실행 종료를 알리기 위해 isComposing 플래그를 false로 변경한다.
- 작업에 사용한 임시 데이터를 삭제한다.
초기 Composition 후 변경 사항 적용
초기 composition 이후 applier.onBeginChanges()를 호출을 통해 Applier는 composition.applyChanges()가 호출되면서 프로세스 중에 기록된 모든 변경 사항을 적용하라는 알림을 받게 된다.
그다음 등록된 모든 RememberedObserver를 전달하므로 RememberObserever를 구체화 한 모든 클래스는 composition에 들어가거나 나갈 때 콜백을 받을 수 있다.
LaunchedEffect, DisposableEffect와 같은 개념이 RememberedObserver를 구현하므로 composition 내의 Composable 수명 주기에 따라 이펙트를 제한할 수 있다.
Composition에 대한 추가 정보
Composition은 자신이 관찰하는 일련의 객체들을 감지할 수 있는 방법을 제공하며, 객체들이 변경될 경우 recomposition을 강제할 수 있다.
가령, 상위 composition에서 CompositionLocal이 변경되면 하위 composition이 recomposition 되도록 강제하기 위해 Recomposer를 통해 작업하게 되는데, 이러한 구현을 위해 composition 들은 상위 compositionContext로 연결되어 있다.
Recomposer
Recomposer는 ControlledComposition을 제어하고, 궁극적으로 변경 사항들을 적용하기 위해 필요시 recomposition을 트리거 한다.
또한 composition을 시작하거나 recomposition 작업을 수행할 스레드, 변경 사항을 적용할 스레드를 결정한다.
'Android' 카테고리의 다른 글
[Android] Compose UI - (1) (0) | 2024.12.16 |
---|---|
[Android] Compose 런타임 - (12) (0) | 2024.12.12 |
[Android] Compose 런타임 - (10) (0) | 2024.12.09 |
[Android] Compose 런타임 - (9) (0) | 2024.12.05 |
[Android] Compose 런타임 - (8) (0) | 2024.12.04 |