Jetpack Compose는 여러 단계에 걸쳐 수정자를 실행합니다. 다음 분석은 일반적인 수정자가 속한 단계와 인수 또는 람다가 평가되는 시점을 보여줍니다.
1단계: 컴포지션 단계
이러한 수정자는 @Composable 본문 내에서 동기적으로 인수를 평가합니다. 여기서 읽은 상태는 컴포저블 다시 시작 범위에 종속 항목을 등록하고 변경되면 전체 리컴포지션을 트리거합니다.
- 정적 측정기준 및 크기 조절 수정자:
Modifier.size(dp),Modifier.width(dp),Modifier.height(dp)Modifier.fillMaxSize(),Modifier.fillMaxWidth(),Modifier.fillMaxHeight()Modifier.wrapContentHeight()Modifier.wrapContentWidth()Modifier.wrapContentSize()Modifier.defaultMinSize()Modifier.requiredSize()Modifier.aspectRatio(ratio)Modifier.weight(weight)(RowScope또는ColumnScope)Modifier.width(IntrinsicSize.Min / Max)Modifier.height(IntrinsicSize.Min / Max)
- 정적 간격 및 인셋:
Modifier.padding(start, top, end, bottom)Modifier.padding(all = dp)Modifier.statusBarsPadding()Modifier.windowInsetsPadding(insets)
- 직접 값 시각적 수정 도구:
Modifier.alpha(float)(컴포지션 중에 상태를 읽음)Modifier.rotate(degrees)(컴포지션 중에 상태를 읽음)Modifier.scale(scaleX, scaleY)(컴포지션 중에 상태를 읽음)Modifier.background(color = Color, shape = Shape)Modifier.border(width, color, shape)Modifier.shadow(elevation, shape)Modifier.clip(shape)Modifier.blur(radius)
- 정적 위치 수정자:
Modifier.offset(x = dp, y = dp)(직접 값 오버로드)Modifier.absoluteOffset(x = dp, y = dp)
- 동적 컴포저블 수정자:
Modifier.composed { ... }(컴포지션 중에 팩토리 본문을 실행함)
2단계: 레이아웃 단계
레이아웃 단계는 별도의 무효화 범위가 있는 두 개의 개별 하위 단계로 나뉩니다.
2A단계: 측정
크기 (width, height)와 제약 조건을 결정합니다. 여기에서 상태를 읽으면 재측정 및 재배치가 트리거됩니다.
Modifier.layout { measurable, constraints -> ... }:layout(w, h)전의 코드는 측정 중에 실행됩니다.
2B단계: 배치 및 레이아웃 콜백
(x, y) 좌표 위치를 결정합니다. 여기에서 상태를 읽으면 재배치만 트리거됩니다 (측정 및 컴포지션 건너뛰기).
Modifier.offset { IntOffset(x, y) }(람다 오버로드)Modifier.absoluteOffset { IntOffset(x, y) }(람다 오버로드)Modifier.layout { ... layout(w, h) { placeable.place(x, y) } }:layout(w, h) { ... }블록 내의 코드입니다.Modifier.onPlaced { layoutCoordinates -> ... }: 배치 중에 상위 좌표가 결정된 후 호출됩니다.Modifier.onSizeChanged { intSize -> ... }: 크기가 변경된 경우 레이아웃 측정 완료 후 호출됩니다.Modifier.onGloballyPositioned { layoutCoordinates -> ... }: 전체 창 레이아웃 패스가 완료된 후 호출됩니다.
3단계: 그리기 단계
이러한 수정자는 캔버스 그리기 중에 실행됩니다. 이러한 블록 내에서 상태를 읽으면 컴포지션과 레이아웃 모두가 건너뛰고 그리기 패스만 실행됩니다.
Modifier.graphicsLayer { ... }:- 람다에서 업데이트된 속성:
alpha,translationX,translationY,scaleX,scaleY,rotationX,rotationY,rotationZ,shadowElevation,shape,clip,renderEffect,transformOrigin
- 람다에서 업데이트된 속성:
Modifier.drawBehind { ... }:- 컴포저블 콘텐츠 뒤에 캔버스 명령어를 그립니다.
Modifier.drawWithContent { ... }:drawContent()로 그리기 순서를 제어합니다.
Modifier.drawWithCache { ... }:- 외부 블록은 크기 또는 레이아웃 변경 시 실행되어
Path,Paint또는Brush객체를 캐시합니다.onDrawBehind또는onDrawWithContent는 각 프레임 그리기에서 실행됩니다.
- 외부 블록은 크기 또는 레이아웃 변경 시 실행되어
리컴포지션 루프 외부 - 관찰 수정자
일부 수정자는 접근성, 사용자 입력, 수명 주기 관찰을 처리하기 위해 세 프레임 단계 외부에서 작동합니다.
시맨틱 및 접근성
접근성 서비스 (TalkBack) 및 테스트를 위한 시맨틱 속성을 처리합니다.
Modifier.semantics { ... }Modifier.clearAndSetSemantics { ... }
입력, 동작, 이벤트
3단계 프레임 렌더링 파이프라인 외부에서 작동하며 OS 동작 이벤트와 사용자 상호작용을 수신합니다.
Modifier.pointerInput(key) { detectTapGestures { ... } }/detectDragGestures/awaitPointerEventScopeModifier.clickable(enabled, onClickLabel) { ... }Modifier.combinedClickable { ... }Modifier.toggleable { ... }Modifier.selectable { ... }Modifier.draggable(...)/Modifier.scrollable(...)/Modifier.draggable2D(...)Modifier.onFocusChanged { focusState -> ... }Modifier.onKeyEvent { keyEvent -> ... }Modifier.onVisibilityChanged { isVisible -> ... }: 콜백은 코루틴에서 구성된 지연 후 컴포저블의 공개 상태가 변경될 때 호출됩니다.
빠른 참조: 가치 대 람다 단계
람다에서 상태 값을 읽으면 읽기가 후반 단계로 지연되어 상태가 변경될 때 이전 단계를 건너뜁니다.
| 수정자 / 패턴 | 직접 가치 (구성) | 람다 변형 (지연된 단계) | 상태가 변경될 때 |
|---|---|---|---|
| 오프셋 | Modifier.offset(x, y) |
Modifier.offset { IntOffset(x, y) } |
레이아웃 (배치) (컴포지션 건너뛰기) |
| 알파 / 불투명도 | Modifier.alpha(alpha) |
Modifier.graphicsLayer { this.alpha = alpha } |
그리기 (구성 및 레이아웃 건너뛰기) |
| 회전 | Modifier.rotate(degrees) |
Modifier.graphicsLayer { rotationZ = degrees } |
그리기 (구성 및 레이아웃 건너뛰기) |
| 확장 | Modifier.scale(scale) |
Modifier.graphicsLayer { scaleX = s; scaleY = s } |
그리기 (구성 및 레이아웃 건너뛰기) |
| 번역 | Modifier.padding(...) |
Modifier.graphicsLayer { translationX = ... } |
그리기 (구성 및 레이아웃 건너뛰기) |
| 배경 색상 | Modifier.background(color) |
Modifier.drawBehind { drawRect(color) } |
그리기 (구성 및 레이아웃 건너뛰기) |
| 스크롤 / 시차 | Modifier.offset(scroll.dp) |
Modifier.offset { IntOffset(0, scroll) } |
레이아웃 (배치) (컴포지션 건너뛰기) |
Modifier.Node 인터페이스 매핑
고성능 Modifier.Node API를 사용하는 맞춤 수정자의 경우 단계가 노드 기능 인터페이스에 직접 매핑됩니다.
| 단계 | Modifier.Node 인터페이스 |
핵심 메서드 |
|---|---|---|
| 레이아웃 (측정 및 배치) | LayoutModifierNode |
measure(measurable, constraints) |
| 레이아웃 (전역 좌표) | GlobalPositionAwareModifierNode |
onGloballyPositioned(coordinates) |
| 레이아웃 (배치) | LayoutAwareModifierNode |
onPlaced(coordinates) onRemeasured(size) |
| 그리기 | DrawModifierNode |
draw(ContentDrawScope) |
| 입력 / 포인터 | PointerInputModifierNode |
onCancelPointerInput() onPointerEvent(...) |
| 시맨틱 | SemanticsModifierNode |
applySemantics(SemanticsPropertyReceiver) |
| 포커스 | FocusEventModifierNode |
onFocusEvent(focusState) |