Modifier la répartition par phase

Jetpack Compose exécute les modificateurs dans différentes phases. La répartition suivante indique à quelle phase appartiennent les modificateurs courants et quand leurs arguments ou lambdas sont évalués.

Phase 1 : Phase de composition

Ces modificateurs évaluent les arguments de manière synchrone dans le corps @Composable. Tout état lu ici enregistre une dépendance avec le champ d'application de redémarrage Composable et déclenche une recomposition complète en cas de modification.

  • Modificateurs de dimension et de taille statiques :
    • Modifier.size(dp), Modifier.width(dp), Modifier.height(dp)
    • Modifier.fillMaxSize(), Modifier.fillMaxWidth(), Modifier.fillMaxHeight()
    • Modifier.wrapContentSize(), Modifier.wrapContentWidth(), Modifier.wrapContentHeight()
    • Modifier.requiredSize(), Modifier.defaultMinSize()
    • Modifier.aspectRatio(ratio)
    • Modifier.weight(weight) (dans RowScope ou ColumnScope)
    • Modifier.width(IntrinsicSize.Min / Max)
    • Modifier.height(IntrinsicSize.Min / Max)
  • Espacements et encarts statiques :
    • Modifier.padding(all = dp), Modifier.padding(start, top, end, bottom)
    • Modifier.windowInsetsPadding(insets), Modifier.statusBarsPadding()
  • Modificateurs visuels de valeur directe :
    • Modifier.alpha(float) (lit l'état lors de la composition)
    • Modifier.rotate(degrees) (lit l'état lors de la composition)
    • Modifier.scale(scaleX, scaleY) (lit l'état lors de la composition)
    • Modifier.background(color = Color, shape = Shape)
    • Modifier.border(width, color, shape)
    • Modifier.shadow(elevation, shape)
    • Modifier.clip(shape)
    • Modifier.blur(radius)
  • Modificateurs de position statique :
    • Modifier.offset(x = dp, y = dp) (surcharge de valeur directe)
    • Modifier.absoluteOffset(x = dp, y = dp)
  • Modificateurs composables dynamiques :
    • Modifier.composed { ... } (exécute le corps de la fabrique lors de la composition)

Phase 2 : Mise en page

La phase de mise en page est divisée en deux sous-étapes distinctes avec des portées d'invalidation distinctes :

Étape 2A : Mesure

Détermine la taille (width, height) et les contraintes. La lecture de l'état ici déclenche une nouvelle mesure et un nouveau placement :

  • Modifier.layout { measurable, constraints -> ... } : le code avant layout(w, h) s'exécute pendant la mesure.

Étape 2B : Callbacks de placement et de mise en page

Détermine la position des coordonnées (x, y). L'état lu ici ne déclenche que le repositionnement (en ignorant la mesure et la composition) :

  • Modifier.offset { IntOffset(x, y) } (surcharge lambda)
  • Modifier.absoluteOffset { IntOffset(x, y) } (surcharge lambda)
  • Modifier.layout { ... layout(w, h) { placeable.place(x, y) } } : code à l'intérieur du bloc layout(w, h) { ... }.
  • Modifier.onPlaced { layoutCoordinates -> ... } : appelé une fois les coordonnées du parent déterminées lors du placement.
  • Modifier.onSizeChanged { intSize -> ... } : appelé une fois la mesure de la mise en page terminée si la taille a changé.
  • Modifier.onGloballyPositioned { layoutCoordinates -> ... } : appelé une fois que la passe de mise en page de la fenêtre entière est terminée.

Phase 3 : Phase de dessin

Ces modificateurs s'exécutent lors du dessin du canevas. La lecture de l'état à l'intérieur de ces blocs ignore la composition et la mise en page, et n'exécute que la passe de dessin :

  • Modifier.graphicsLayer { ... } :
    • Propriétés mises à jour dans le lambda : alpha, translationX, translationY, scaleX, scaleY, rotationX, rotationY, rotationZ, shadowElevation, shape, clip, renderEffect, transformOrigin.
  • Modifier.drawBehind { ... } :
    • Dessine les commandes Canvas derrière le contenu composable.
  • Modifier.drawWithContent { ... } :
    • Contrôle l'ordre de dessin avec drawContent().
  • Modifier.drawWithCache { ... } :
    • Le bloc extérieur s'exécute lors des modifications de taille ou de mise en page pour mettre en cache les objets Path, Paint ou Brush. onDrawBehind ou onDrawWithContent s'exécute à chaque dessin de frame.

En dehors de la boucle de recomposition : modificateurs d'observation

Certains modificateurs fonctionnent en dehors des trois phases de frame pour gérer l'accessibilité, l'entrée utilisateur et les observations du cycle de vie.

Sémantique et accessibilité

Traite les propriétés sémantiques pour les services d'accessibilité (TalkBack) et les tests :

  • Modifier.semantics { ... }
  • Modifier.clearAndSetSemantics { ... }

Saisie, gestes et événements

Fonctionne en dehors du pipeline de rendu de frame en trois phases, en recevant les événements de mouvement de l'OS et les interactions utilisateur :

  • Modifier.pointerInput(key) { detectTapGestures { ... } } / detectDragGestures / awaitPointerEventScope
  • Modifier.clickable(enabled, onClickLabel) { ... }
  • Modifier.combinedClickable { ... }
  • Modifier.toggleable { ... }
  • Modifier.selectable { ... }
  • Modifier.draggable(...) / Modifier.scrollable(...) / Modifier.draggable2D(...)
  • Modifier.onFocusChanged { focusState -> ... }
  • Modifier.onKeyEvent { keyEvent -> ... }
  • Modifier.onVisibilityChanged { isVisible -> ... } : le rappel est invoqué lorsque la visibilité d'un composable change après le délai configuré, dans une coroutine.

Référence rapide : phase de valeur par rapport à la phase lambda

La lecture d'une valeur d'état dans un lambda reporte la lecture à une phase ultérieure, ce qui ignore les phases précédentes lorsque cet état change :

Modificateur / Motif Valeur directe (composition) Variante Lambda (phase différée) Lorsque l'état change
Décalage (offset) Modifier.offset(x, y) Modifier.offset { IntOffset(x, y) } Mise en page (emplacement) (ignorer la composition)
Alpha / Opacité Modifier.alpha(alpha) Modifier.graphicsLayer { this.alpha = alpha } Dessin (Composition et mise en page ignorées)
Rotation Modifier.rotate(degrees) Modifier.graphicsLayer { rotationZ = degrees } Dessin (Composition et mise en page ignorées)
Évoluer Modifier.scale(scale) Modifier.graphicsLayer { scaleX = s; scaleY = s } Dessin (Composition et mise en page ignorées)
Translation Modifier.padding(...) Modifier.graphicsLayer { translationX = ... } Dessin (Composition et mise en page ignorées)
Couleur d'arrière-plan Modifier.background(color) Modifier.drawBehind { drawRect(color) } Dessin (Composition et mise en page ignorées)
Défilement / Parallaxe Modifier.offset(scroll.dp) Modifier.offset { IntOffset(0, scroll) } Mise en page (emplacement) (ignorer la composition)

Mappage de l'interface Modifier.Node

Pour les modificateurs personnalisés utilisant l'API Modifier.Node hautes performances, les phases correspondent directement aux interfaces de capacité des nœuds :

Phase Interface Modifier.Node Méthodes principales
Mise en page (mesurer et placer) LayoutModifierNode measure(measurable, constraints)
Mise en page (coordonnées globales) GlobalPositionAwareModifierNode onGloballyPositioned(coordinates)
Mise en page (emplacement) LayoutAwareModifierNode onRemeasured(size), onPlaced(coordinates)
Dessin DrawModifierNode draw(ContentDrawScope)
Entrée / Pointeur PointerInputModifierNode onPointerEvent(...), onCancelPointerInput()
Sémantique SemanticsModifierNode applySemantics(SemanticsPropertyReceiver)
Mise au point FocusEventModifierNode onFocusEvent(focusState)