Optimiser la fréquence d'images avec la fréquence d'actualisation adaptative

Lorsqu'une animation est lancée dans Android, l'écran passe souvent à la fréquence d'actualisation maximale pour garantir une expérience fluide. Pour les petites animations telles que les barres de progression et les visualisateurs audio, ce taux de rafraîchissement élevé est inutile et entraîne une forte consommation d'énergie.

À partir d'Android 15, grâce à la fonctionnalité de fréquence d'actualisation adaptative (ARR), les appareils sur lesquels elle est activée peuvent réduire la résidence à haute fréquence d'actualisation de deux manières :

  • Grâce aux nouvelles optimisations de la gestion de la fréquence d'images de la plate-forme, les applications peuvent s'afficher par défaut à une fréquence d'images inférieure et ne passer à une fréquence d'images élevée que lorsque cela est nécessaire.
  • La fréquence d'actualisation de l'écran correspond dynamiquement à la fréquence de rendu du contenu sans saccades.

Bien que la plupart des applications devraient bénéficier de l'ARR sans aucune modification, vous pouvez également remplacer le comportement par défaut de la fréquence d'images si nécessaire.

Cette page décrit les éléments suivants :

  • Comment la fréquence d'images de chaque vue est-elle déterminée ?
  • Règle générale pour déterminer la fréquence d'images dans ARR.
  • Découvrez comment remplacer manuellement le comportement par défaut de la fréquence d'images.

Mécanisme de vote dans la vue

Dans le système de vues d'Android, chaque vue de la hiérarchie de l'UI peut exprimer sa fréquence d'images préférée. Ces préférences sont collectées et combinées pour déterminer une fréquence d'images finale pour chaque frame. Pour ce faire, un mécanisme de vote est utilisé. Chaque vue vote en fonction de son attribut de fréquence d'images, qui peut être une catégorie ou une fréquence spécifique. Les vues votent généralement lorsqu'elles sont dessinées ou mises à jour. Ces votes sont combinés pour déterminer une fréquence d'images finale, qui est ensuite envoyée au niveau inférieur en tant qu'indication pour le rendu.

Actuellement, la plupart des vues sont définies par défaut sur une fréquence d'images "normale", souvent de 60 Hz. Pour des fréquences d'images plus élevées, vous pouvez utiliser des API spécifiques pour personnaliser les préférences, le système sélectionnant généralement la fréquence d'images la plus élevée. Pour en savoir plus sur l'utilisation de ces API, consultez la section Définir la fréquence d'images ou la catégorie. Les règles générales concernant les fréquences d'images sont décrites dans la section Règles générales concernant l'ARR.

Catégories de fréquence d'images

Dans la classe View, différentes catégories de fréquence d'images peuvent être utilisées dans le vote. Voici la description de chaque catégorie :

  • REQUESTED_FRAME_RATE_CATEGORY_DEFAULT : cette valeur peut être définie pour revenir au comportement par défaut, indiquant que cette vue ne contient aucune donnée pour la fréquence d'images.
  • REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE : la vue n'aura aucune incidence sur la fréquence d'images. Cela signifie que, même si la vue est active, le framework ne la prendra pas en compte pour déterminer la fréquence d'images.
  • REQUESTED_FRAME_RATE_CATEGORY_NORMAL : indique une fréquence d'images intermédiaire adaptée aux animations qui ne nécessitent pas de fréquence d'images plus élevée ou qui ne bénéficient pas d'une grande fluidité. Il est généralement de 60 Hz ou proche de cette valeur.
  • REQUESTED_FRAME_RATE_CATEGORY_HIGH : indique une fréquence d'images adaptée aux animations qui nécessitent une fréquence d'images élevée, ce qui peut améliorer la fluidité, mais aussi augmenter la consommation d'énergie.

Une vue ne vote que si elle nécessite un redessin. La fréquence d'images finale est déterminée par le vote le plus élevé. Par exemple, si tous les votes sont pour "Normal", "Normal" est sélectionné. Lorsque des votes "Normal" et "Élevé" sont enregistrés, le vote "Élevé" est choisi.

Fréquence d'images

En plus des catégories de fréquence d'images, une vue peut également spécifier une fréquence d'images préférée, telle que 30, 60 ou 120 Hz. Lorsque plusieurs votes de fréquence d'images sont exprimés, la fréquence d'images finale est déterminée par les règles suivantes :

  • Multiples les uns des autres : si les fréquences d'images votées sont des multiples les unes des autres, la valeur la plus élevée est choisie. Par exemple, s'il y a deux votes (30 Hz et 90 Hz), 90 Hz est sélectionné comme fréquence d'images finale.
  • Les valeurs ne sont pas des multiples les unes des autres :
    • Si l'un des votes est supérieur à 60 Hz, il est considéré comme un vote "Élevé".
    • Si tous les votes sont de 60 Hz ou moins, ils sont comptabilisés comme des votes "Normaux".

De plus, si vous combinez des valeurs de fréquence d'images et des catégories de fréquence d'images, la valeur la plus élevée détermine généralement la fréquence de rendu finale. Par exemple, avec une combinaison d'un vote de 60 Hz et d'un vote "Élevé", ou d'un vote de 120 Hz et d'un vote "Normal", le taux de rendu serait généralement défini sur 120 Hz.

En plus des votes d'une application, d'autres indices peuvent être envoyés à la couche inférieure à partir de différents composants d'un même frame. Beaucoup d'entre eux peuvent provenir de composants de l'UI système, tels que la barre de notifications, la barre d'état, la barre de navigation, etc. Les valeurs de fréquence d'images finales sont déterminées en fonction des votes de plusieurs composants.

Définir la fréquence d'images ou la catégorie

Dans certaines circonstances, vous pouvez avoir une fréquence d'images préférée pour une vue. Par exemple, vous pouvez définir la fréquence d'images préférée sur "Élevée" pour une vue afin d'augmenter la fréquence d'images si une animation semble saccadée. De plus, si une animation lente ou statique est superposée à une vidéo (généralement lue à 24 ou 30 Hz), vous pouvez préférer que l'animation s'exécute à une fréquence inférieure à "Normale" pour réduire la consommation d'énergie.

Vous pouvez utiliser les API setRequestedFrameRate() et getRequestedFrameRate() pour désigner la fréquence d'images ou la catégorie préférée d'une vue donnée.

Kotlin

// Set the preferred frame rate category to a View

// set the frame rate category to NORMAL
view.requestedFrameRate = View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL
// set the frame rate category to HIGH
view.requestedFrameRate = View.REQUESTED_FRAME_RATE_CATEGORY_HIGH
// reset the frame rate category
view.requestedFrameRate = View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT

// Set the preferred frame rate to a View

// set the frame rate to 30
view.requestedFrameRate = 30f
// set the frame rate to 60
view.requestedFrameRate = 60f
// set the frame rate to 120
view.requestedFrameRate = 120f

Java

// Set the preferred frame rate category to a View

// set the frame rate category to NORMAL
view.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL);
// set the frame rate category to HIGH
view.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_HIGH);
// reset the frame rate category
view.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);

// Set the preferred frame rate to a View

// set the frame rate to 30
view.setRequestedFrameRate(30);
// set the frame rate to 60
view.setRequestedFrameRate(60);
// set the frame rate to 120
view.setRequestedFrameRate(120);

Pour voir un exemple d'utilisation, consultez TextureView.

Règlement général sur l'ARR

Dans la section précédente, nous avons vu que la plupart des animations s'affichent à 60 Hz par défaut, car chaque vue a la fréquence d'images "Normal" définie comme fréquence d'images préférée. Toutefois, il existe des exceptions où la fréquence d'images est augmentée à "Élevée" pour garantir des animations plus fluides.

Voici les règles générales concernant l'ARR :

  • Accélération tactile : lorsqu'un événement tactile (MotionEvent.ACTION_DOWN) est détecté, la fréquence d'actualisation est augmentée sur "Élevée" pendant un certain temps après la fin du contact pour maintenir la réactivité.
  • Gestes de balayage : les gestes de balayage sont gérés différemment. La fréquence d'actualisation diminue progressivement à mesure que la vitesse de balayage ralentit. Pour en savoir plus sur ce comportement, consultez la section Amélioration du défilement.
  • Lancement d'applications et transitions de fenêtres : le taux d'actualisation est également augmenté pendant un certain temps lors du lancement d'applications, de l'initialisation de fenêtres et des transitions de fenêtres pour garantir une expérience visuelle fluide.
  • Animations : les animations impliquant des mouvements ou des changements de taille bénéficient automatiquement d'une fréquence d'actualisation plus élevée pour améliorer la fluidité lorsque la position ou la taille d'une vue changent.
  • SurfaceView et TextureView : les fréquences d'images définies explicitement pour TextureView et SurfaceView sont respectées et appliquées en conséquence.

Activer et désactiver l'amplification tactile

Vous pouvez activer et/ou désactiver l'amplification tactile au niveau de Window. Par défaut, lorsqu'un utilisateur appuie sur l'écran et retire son doigt, la fréquence de rendu augmente pendant un certain temps. Les API setFrameRateBoostOnTouchEnabled() et getFrameRateBoostOnTouchEnabled() vous permettent d'empêcher l'augmentation de la fréquence de rendu lorsqu'un Window spécifique est touché.

Kotlin

// disable touch boost on a Window
window.isFrameRateBoostOnTouchEnabled = false 
// enable touch boost on a Window
window.isFrameRateBoostOnTouchEnabled = true
// check if touch boost is enabled on a Window
val isTouchBoostEnabled = window.isFrameRateBoostOnTouchEnabled

Java

// disable touch boost on a Window
window.setFrameRateBoostOnTouchEnabled(false)
// enable touch boost on a Window
window.setFrameRateBoostOnTouchEnabled(true)
// check if touch boost is enabled on a Window
window.getFrameRateBoostOnTouchEnabled()

Amélioration du défilement

L'un des principaux cas d'utilisation de l'optimisation dynamique de la fréquence d'images est l'amélioration de l'expérience de défilement (fling). De nombreuses applications s'appuient fortement sur le geste de balayage vers le haut des utilisateurs pour afficher de nouveaux contenus. L'amélioration du défilement de l'ARR ajuste dynamiquement le taux d'actualisation lorsque le geste de balayage ralentit, ce qui réduit progressivement la fréquence d'images. Cela permet un rendu plus efficace tout en conservant un défilement fluide.

Cette amélioration s'applique spécifiquement aux composants d'UI à défilement, y compris ScrollView, ListView et GridView, et peut ne pas être disponible pour toutes les implémentations personnalisées.

La fonctionnalité de défilement de l'ARR est disponible pour RecyclerView et NestedScrollView. Pour activer cette fonctionnalité dans votre application, passez aux dernières versions de AndroidX.recyclerview et AndroidX.core. Pour en savoir plus, consultez le tableau ci-dessous.

Bibliothèque

Version

AndroidX.recyclerview

1.4.0

AndroidX.core

1.15.0

Définir les informations de vélocité

Si vous disposez d'un composant à défilement personnalisé et que vous souhaitez profiter de la fonctionnalité de défilement, appelez setFrameContentVelocity() à chaque frame lors du défilement fluide ou du glissement d'un geste vif. Voici un exemple :

Kotlin

// set the velocity to a View (1000 pixels/Second)
view.frameContentVelocity = 1000f
// get the velocity of a View
val velocity = view.frameContentVelocity

Java

// set the velocity to a View
view.setFrameContentVelocity(velocity);

// get the velocity of a View
final float velocity = view.getFrameContentVelocity()

Pour obtenir d'autres exemples, consultez RecyclerView et ScrollView. Pour définir correctement la vitesse, calculez manuellement la vitesse du contenu (en pixels par seconde) si les informations requises ne peuvent pas être obtenues à partir de Scroller ou OverScroller.

Notez que si setFrameContentVelocity() et getFrameContentVelocity() sont appelés sur des vues qui ne sont pas des composants à faire défiler, ils n'auront aucun effet, car le mouvement déclenche automatiquement une fréquence d'images plus élevée en fonction de la règle actuelle.

Les informations sur la vélocité sont essentielles pour ajuster la fréquence de rendu. Par exemple, prenons le cas du geste de balayage rapide. Au début, la vitesse d'un balayage peut être élevée, ce qui nécessite une fréquence de rendu plus élevée pour assurer la fluidité. À mesure que le geste progresse, la vitesse diminue, ce qui permet de réduire la fréquence de rendu.

Activer et désactiver ARR

L'ARR est activé par défaut pour améliorer l'efficacité énergétique. Vous pouvez désactiver cette fonctionnalité, mais nous vous le déconseillons, car l'application consommerait plus d'énergie. Ne désactivez cette fonctionnalité que si vous rencontrez des problèmes qui ont un impact important sur l'expérience utilisateur.

Pour activer ou désactiver l'ARR, utilisez l'API setFrameRatePowerSavingsBalanced() sur un Window ou l'API isFrameRatePowerSavingsBalanced() via votre fichier styles.xml.

L'extrait suivant montre comment activer ou désactiver ARR sur un Window :

Kotlin

// disable ARR on a Window
window.isFrameRatePowerSavingsBalanced = false 
// enable ARR on a Window
window.isFrameRatePowerSavingsBalanced = true  
// check if ARR is enabled on a Window
val isAdaptiveRefreshRateEnabled = window.isFrameRatePowerSavingsBalanced

Java

// disable ARR on a Window
window.setFrameRatePowerSavingsBalanced(false)
// enable ARR on a Window
window.setFrameRatePowerSavingsBalanced(true)
// check if ARR is enabled on a Window
window.isFrameRatePowerSavingsBalanced()

Pour désactiver ARR via le fichier styles.xml, ajoutez l'élément suivant à votre style dans res/values/styles.xml :

<style name="frameRatePowerSavingsBalancedDisabled">
    <item name="android:windowIsFrameRatePowerSavingsBalanced">false</item>
</style>

ARR pour Compose

Compose 1.9 est également compatible avec la fréquence d'actualisation adaptative. Dans le système de vues, vous utilisez la méthode setRequestedFrameRate() pour demander une fréquence d'images spécifique pour une vue. Dans Compose, un nouveau modificateur vous permet de spécifier la fréquence d'images d'un composable. Ce modificateur fonctionne de la même manière que setRequestedFrameRate(). Il accepte une valeur de fréquence d'images positive (en Hz) ou une catégorie de fréquence d'images prédéfinie, FrameRateCategory.

Voici les signatures des API :

Dans l'extrait de code ci-dessous, le nouveau modificateur de fréquence d'images (Modifier.requestedFrameRate(120f)) est appliqué à un composable Text. Ce modificateur permet au composable Text de demander une fréquence d'images préférée de 120 lors du dessin ou de l'animation (par exemple, avec des changements d'opacité) :

var targetAlpha by remember { mutableFloatStateOf(1f) }
val alpha by
    animateFloatAsState(
        targetValue = targetAlpha,
        animationSpec = tween(durationMillis = 1000)
    )

Button(
    onClick = { targetAlpha = if (targetAlpha == 1f) 0.2f else 1f },
    modifier =
        Modifier.background(LocalContentColor.current.copy(alpha = alpha))
) {
    Text(
        text = "Click",
        color = LocalContentColor.current.copy(alpha = alpha),
        modifier = Modifier.preferredFrameRate(120f)
     // You can also pass frame rate category such as FrameRateCategory.High  to increase the frame rate
    )
  }

Les fréquences d'images préférées de tous les composables sont ensuite collectées et consolidées pour déterminer la fréquence d'images finale pour chaque frame. Pour en savoir plus, consultez SetFrameRateSample et SetFrameRateCategorySample.