Cuando se inicia una animación en Android, la pantalla suele aumentar su frecuencia de actualización máxima para garantizar una experiencia fluida. Para animaciones pequeñas, como barras de progreso y visualizadores de audio, esta alta frecuencia de actualización es innecesaria y genera un alto consumo de energía.
A partir de Android 15, con la función de frecuencia de actualización adaptable (ARR), los dispositivos habilitados pueden reducir la permanencia de la frecuencia de actualización alta en dos aspectos:
- Con las nuevas optimizaciones de administración de la velocidad de fotogramas de la plataforma, las apps pueden renderizar con una velocidad de fotogramas más baja de forma predeterminada y solo aumentar a una velocidad de fotogramas alta cuando sea necesario.
- La frecuencia de actualización de la pantalla coincide de forma dinámica con la frecuencia de renderización del contenido sin interrupciones.
Si bien la mayoría de las apps deberían beneficiarse del ARR sin modificaciones, también puedes anular el comportamiento predeterminado de la velocidad de fotogramas según sea necesario.
En esta página, se describe lo siguiente:
- Cómo se determina la frecuencia de fotogramas de cada vista
- Es la política general que determina la frecuencia de fotogramas que se establece en ARR.
- Cómo anular manualmente el comportamiento predeterminado de la velocidad de fotogramas
El mecanismo de votación de la vista
En el sistema de View de Android, cada View en la jerarquía de la IU puede expresar su velocidad de fotogramas preferida. Estas preferencias se recopilan y combinan para determinar una velocidad de fotogramas final para cada fotograma. Esto se logra a través de un mecanismo de votación en el que cada View vota según su atributo de frecuencia de fotogramas, que puede ser una categoría o una frecuencia específica. Por lo general, las vistas votan cuando se dibujan o actualizan. Estos votos se combinan para determinar una velocidad de fotogramas final, que luego se envía a la capa de nivel inferior como una sugerencia para la renderización.
Actualmente, la mayoría de las vistas tienen una velocidad de fotogramas "Normal" predeterminada, que suele establecerse en 60 Hz. Para velocidades de fotogramas más altas, puedes usar APIs específicas para personalizar las preferencias, y el sistema suele seleccionar la velocidad de fotogramas más alta. Para obtener más información sobre el uso de estas APIs, consulta la sección Cómo establecer la frecuencia de fotogramas o la categoría. Las políticas generales sobre las frecuencias de fotogramas se describen en la sección Política general sobre ARR.
Categorías de velocidad de fotogramas
En la clase View
, hay diferentes categorías de frecuencia de fotogramas que se pueden usar en la votación. A continuación, se incluye la descripción de cada categoría:
REQUESTED_FRAME_RATE_CATEGORY_DEFAULT
: Este valor se puede establecer para volver al comportamiento predeterminado, lo que indica que esta vista no tiene datos para la velocidad de fotogramas.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE
: La vista no influirá de forma explícita en la velocidad de fotogramas. Esto significa que, incluso si la vista está activa, el framework no la tendrá en cuenta cuando determine la velocidad de fotogramas.REQUESTED_FRAME_RATE_CATEGORY_NORMAL
: Indica una velocidad de fotogramas media adecuada para animaciones que no requieren velocidades de fotogramas más altas o que no se benefician de una gran fluidez. Por lo general, es de 60 Hz o cerca de esa frecuencia.REQUESTED_FRAME_RATE_CATEGORY_HIGH
: Indica una velocidad de fotogramas adecuada para animaciones que requieren una velocidad de fotogramas alta, lo que puede aumentar la fluidez, pero también el uso de energía.
Una vista solo vota si requiere volver a dibujarse. La velocidad de fotogramas final se determina según el voto más alto. Por ejemplo, si todos los votos son para "Normal", se selecciona "Normal". Cuando se producen votos de "Normal" y "Alto", se elige "Alto".
Velocidad de fotogramas
Además de las categorías de frecuencia de fotogramas, una vista también puede especificar una frecuencia de fotogramas preferida, como 30, 60 o 120 Hz. Cuando se emiten varios votos de frecuencia de fotogramas, la frecuencia de fotogramas final se determina según las siguientes reglas:
- Múltiplos entre sí: Si los fotogramas por segundo votados son múltiplos entre sí, se elige el valor más alto. Por ejemplo, si hay dos votos (30 Hz y 90 Hz), se selecciona 90 Hz como la velocidad de fotogramas final.
- No son múltiplos entre sí:
- Si alguno de los votos es superior a 60 Hz, se considera un voto de "Alta".
- Si todos los votos son de 60 Hz o menos, se considera un voto "Normal".
Además, si hay una combinación de valores de velocidad de fotogramas y categorías de velocidad de fotogramas, el valor más alto suele determinar la velocidad de procesamiento final. Por ejemplo, con una combinación de un voto de 60 Hz y un voto de "Alto", o un voto de 120 Hz y un voto de "Normal", la frecuencia de renderización se establecería en 120 Hz.
Además de los votos de una app, también puede haber otras sugerencias que se envían a la capa de nivel inferior desde diferentes componentes dentro del mismo fotograma. Muchas de estas pueden originarse en componentes de la IU del sistema, como la sombra de notificaciones, la barra de estado, la barra de navegación y otros. Los valores finales de la velocidad de fotogramas se determinan en función de los votos de varios componentes.
Cómo establecer la categoría o la velocidad de fotogramas
En ciertas circunstancias, es posible que tengas una velocidad de fotogramas preferida para una vista. Por ejemplo, puedes establecer la velocidad de fotogramas preferida en "Alta" para una View y, así, aumentarla si una animación no se ve fluida. Además, si hay una animación lenta o estática sobre un video (que suele reproducirse a 24 o 30 Hz), es posible que prefieras que la animación se ejecute a una velocidad inferior a "Normal" para reducir el consumo de energía.
Puedes usar las APIs de setRequestedFrameRate()
y getRequestedFrameRate()
para designar la categoría o la velocidad de fotogramas preferida de una View determinada.
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);
Para ver un ejemplo de uso, consulta TextureView
.
Política general de ARR
En la sección anterior, analizamos que la mayoría de las animaciones se muestran a 60 Hz de forma predeterminada, ya que cada View tiene establecido "Normal" como la velocidad de fotogramas preferida. Sin embargo, hay excepciones en las que la velocidad de fotogramas se incrementa a "Alta" para garantizar animaciones más fluidas.
La política general de ARR es la siguiente:
- Aumento de respuesta táctil: Cuando se detecta un evento táctil (
MotionEvent.ACTION_DOWN
), la frecuencia de actualización se aumenta a "Alta" durante un tiempo después de que se suelta el toque para mantener la capacidad de respuesta. - Gestos de deslizamiento: Los gestos de deslizamiento se controlan de manera diferente: la frecuencia de actualización disminuye gradualmente a medida que se reduce la velocidad del deslizamiento. Puedes encontrar detalles sobre este comportamiento en la sección Mejora del desplazamiento.
- Transiciones de ventanas y de inicio de apps: La frecuencia de actualización también se incrementa durante un tiempo cuando se inician apps, se inicializan ventanas y se realizan transiciones de ventanas para garantizar una experiencia visual fluida.
- Animaciones: Las animaciones que implican cambios de movimiento o tamaño reciben automáticamente una frecuencia de actualización más alta para mejorar la fluidez cuando cambia la posición o el tamaño de una vista.
SurfaceView
yTextureView
: Se respetan y aplican según corresponda las velocidades de fotogramas establecidas de forma explícita paraTextureView
ySurfaceView
.
Cómo habilitar e inhabilitar la amplificación táctil
Puedes habilitar o inhabilitar el aumento de sensibilidad táctil en el nivel Window
. De forma predeterminada, cuando un usuario toca la pantalla y levanta el dedo, la velocidad de renderización aumenta durante un tiempo. Las APIs de setFrameRateBoostOnTouchEnabled()
y getFrameRateBoostOnTouchEnabled()
te permiten evitar que aumente la frecuencia de renderización cuando se toca un Window
específico.
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()
Mejora del desplazamiento
Un caso de uso clave para optimizar la velocidad de fotogramas de forma dinámica es mejorar la experiencia de desplazamiento (deslizamiento). Muchas aplicaciones dependen en gran medida de que los usuarios deslicen el dedo hacia arriba para ver contenido nuevo. La mejora de desplazamiento de ARR ajusta de forma dinámica la frecuencia de actualización a medida que el gesto de deslizamiento se ralentiza, lo que reduce gradualmente la frecuencia de fotogramas. Esto proporciona una renderización más eficiente y, al mismo tiempo, mantiene un desplazamiento fluido.
Esta mejora se aplica específicamente a los componentes de la IU desplazables, incluidos ScrollView
, ListView
y GridView
, y es posible que no esté disponible para todas las implementaciones personalizadas.
La función de desplazamiento del ARR está disponible para RecyclerView
y NestedScrollView
. Para habilitar esta función en tu app, actualiza a las versiones más recientes de AndroidX.recyclerview
y AndroidX.core
. Consulta la siguiente tabla para obtener más detalles.
Biblioteca |
Versión |
|
1.4.0 |
|
1.15.0 |
Cómo establecer la información de velocidad
Si tienes un componente desplazable personalizado y quieres aprovechar la función de desplazamiento, llama a setFrameContentVelocity()
en cada fotograma mientras se realiza el desplazamiento suave o el gesto de arrastrar y soltar. Consulta el siguiente fragmento de código para ver un ejemplo:
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()
Para obtener más ejemplos, consulta RecyclerView
y ScrollView
. Para establecer la velocidad correctamente, calcula la velocidad del contenido (píxeles por segundo) de forma manual si no se puede obtener la información requerida de Scroller
o OverScroller
.
Ten en cuenta que, si se llama a setFrameContentVelocity()
y getFrameContentVelocity()
en Views que no son componentes desplazables, no tendrán ningún efecto, ya que el movimiento activa automáticamente una mayor velocidad de fotogramas según la política actual.
La información de velocidad es fundamental para ajustar la frecuencia de renderización. Por ejemplo, considera el gesto de deslizar. Al principio, la velocidad de un toque puede ser alta, lo que requiere una tasa de renderización más alta para garantizar la fluidez. A medida que avanza el gesto, la velocidad disminuye, lo que permite reducir la frecuencia de renderización.
Habilita y deshabilita ARR
ARR está habilitado de forma predeterminada para mejorar la eficiencia energética. Si bien puedes inhabilitar esta función, no se recomienda hacerlo, ya que la app consumirá más energía. Solo considera inhabilitar esta función si encuentras problemas que afecten significativamente la experiencia del usuario.
Para habilitar o inhabilitar ARR, usa la API de setFrameRatePowerSavingsBalanced()
en un Window
o la API de isFrameRatePowerSavingsBalanced()
a través de tu archivo styles.xml
.
En el siguiente fragmento, se muestra cómo habilitar o inhabilitar ARR en 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()
Para inhabilitar el ARR a través del archivo styles.xml
, agrega el siguiente elemento a tu estilo en res/values/styles.xml
:
<style name="frameRatePowerSavingsBalancedDisabled">
<item name="android:windowIsFrameRatePowerSavingsBalanced">false</item>
</style>
ARR para Compose
Compose 1.9 también agrega compatibilidad con la frecuencia de actualización adaptable.
En el sistema de vistas, usas el método setRequestedFrameRate()
para solicitar una velocidad de fotogramas específica para una vista. En Compose, un nuevo modificador te permite especificar la velocidad de fotogramas para un elemento componible. Este modificador funciona de manera similar a setRequestedFrameRate()
, ya que acepta un valor de frecuencia de fotogramas positivo (en Hz) o una categoría de frecuencia de fotogramas predefinida, FrameRateCategory
.
Las firmas de las APIs son las siguientes:
Modifier.preferredFrameRate(frameRate: Float)
Modifier.preferredFrameRate(frameRateCategory: FrameRateCategory)
En el siguiente fragmento, el nuevo modificador de velocidad de fotogramas (Modifier.requestedFrameRate(120f))
se aplica a un elemento Text
componible. Este modificador hace que el elemento Text
componible solicite una velocidad de fotogramas preferida de 120 cuando se dibuja o se anima (por ejemplo, con cambios de opacidad):
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
)
}
Luego, se recopilan y consolidan las velocidades de fotogramas preferidas de todos los elementos componibles para determinar la velocidad de fotogramas final de cada fotograma. Para obtener más información, consulta SetFrameRateSample
y SetFrameRateCategorySample
.