Quando uma animação é iniciada no Android, a tela geralmente aumenta a taxa de atualização máxima para garantir uma experiência suave. Para animações pequenas, como barras de progresso e visualizadores de áudio, essa alta taxa de atualização é desnecessária e resulta em alto consumo de energia.
A partir do Android 15, com o recurso de taxa de atualização adaptativa (ARR, na sigla em inglês), os dispositivos ativados podem reduzir a taxa de residência de alta atualização em duas frentes:
- Com as novas otimizações de gerenciamento de frame rate da plataforma, os apps podem renderizar com uma frame rate mais baixa por padrão e aumentar para uma frame rate alta apenas quando necessário.
- A taxa de atualização da tela corresponde dinamicamente à taxa de renderização do conteúdo sem interrupções.
Embora a maioria dos apps se beneficie do ARR sem modificações, você também pode substituir o comportamento padrão da taxa de frames conforme necessário.
Esta página descreve o seguinte:
- Como a taxa de frames de cada visualização é determinada.
- A política geral de como a ARR determina a taxa de frames.
- Como substituir manualmente o comportamento padrão da taxa de frames.
O mecanismo de votação da visualização
No sistema de visualização do Android, cada visualização na hierarquia da interface pode expressar a taxa de quadros preferida. Essas preferências são coletadas e combinadas para determinar uma taxa de frames final para cada frame. Isso é feito por um mecanismo de votação em que cada visualização vota com base no atributo de taxa de frames, que pode ser uma categoria ou uma taxa específica. As visualizações geralmente votam quando são exibidas ou atualizadas. Esses votos são combinados para determinar uma taxa de frames final, que é enviada para a camada de nível inferior como uma dica para renderização.
Atualmente, a maioria das visualizações usa uma taxa de frames "normal", que geralmente é definida como 60 Hz. Para taxas de frames mais altas, use APIs específicas para personalizar as preferências. O sistema geralmente seleciona a taxa de frames mais alta. Para mais informações sobre o uso dessas APIs, consulte a seção Definir a taxa de frames ou a categoria. As políticas gerais sobre taxas de frames são descritas na seção Política geral de ARR.
Categorias de frame rate
Na classe View
, há diferentes categorias de taxa de frames que podem ser
usadas na votação. Confira a descrição de cada categoria:
REQUESTED_FRAME_RATE_CATEGORY_DEFAULT
: esse valor pode ser definido para retornar ao comportamento padrão, indicando que essa visualização não tem dados para a taxa de frames.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE
: a visualização não influencia explicitamente a taxa de frames. Isso significa que, mesmo que a visualização esteja ativa, o framework não a considera ao determinar a taxa de frames.REQUESTED_FRAME_RATE_CATEGORY_NORMAL
: indica uma frame rate média adequada para animações que não exigem frame rates mais altas ou não se beneficiam de uma alta fluidez. Normalmente, é 60 Hz ou algo próximo disso.REQUESTED_FRAME_RATE_CATEGORY_HIGH
: indica uma taxa de frames adequada para animações que exigem uma taxa de frames alta, o que pode aumentar a fluidez, mas também o consumo de energia.
Uma visualização vota apenas se ela precisar ser redesenhada. A taxa de frames final é determinada pela votação mais alta. Por exemplo, se todos os votos forem para "Normal", "Normal" será selecionado. Quando os votos "Normal" e "Alta" ocorrem, "Alta" é escolhido.
Frame rate
Além das categorias de taxa de frames, uma visualização também pode especificar uma taxa de frames preferencial, como 30, 60 ou 120 Hz. Quando vários votos de taxa de frames são dados, a taxa de frames final é determinada pelas seguintes regras:
- Vários valores: se as taxas de frames votadas forem múltiplos uma da outra, o valor mais alto será escolhido. Por exemplo, se houver dois votos, 30 Hz e 90 Hz, 90 Hz será selecionado como a taxa de frames final.
- Não são múltiplos umas das outras:
- Se qualquer um dos votos for maior que 60 Hz, ele será considerado "Alto".
- Se todos os votos forem de 60 Hz ou menos, ele será considerado "normal".
Além disso, se houver uma combinação de valores e categorias de frame rate, o valor mais alto normalmente determina a taxa de renderização final. Por exemplo, com uma combinação de uma votação de 60 Hz e uma votação "Alta" ou uma votação de 120 Hz e uma votação "Normal", a taxa de renderização normalmente é definida como 120 Hz.
Além dos votos de um app, também podem ser enviadas outras dicas à camada de nível inferior de diferentes componentes no mesmo frame. Muitas delas podem ter origem em componentes da interface do sistema, como a sombra de notificação, a barra de status, a barra de navegação e outras. Os valores finais da taxa de frames são determinados com base nos votos de vários componentes.
Definir a taxa de frames ou a categoria
Em determinadas circunstâncias, você pode ter uma taxa de frames preferida para uma visualização. Por exemplo, você pode definir a taxa de frames preferida como "Alta" para uma visualização e aumentar a taxa de frames se uma animação parecer irregular. Além disso, se houver uma animação lenta ou estática sobre um vídeo (normalmente reproduzido a 24 ou 30 Hz), talvez seja preferível que a animação seja executada a uma taxa menor que "Normal" para reduzir o consumo de energia.
É possível usar as APIs setRequestedFrameRate()
e
getRequestedFrameRate()
para designar a taxa de frames ou
a categoria preferida de uma determinada visualização.
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 conferir um exemplo de uso, consulte TextureView
.
Política geral de ARR
Na seção anterior, discutimos que a maioria das animações é exibida a 60 Hz por padrão, já que cada visualização tem "Normal" definido como a taxa de frames preferida. No entanto, há exceções em que a taxa de frames é aumentada para "Alta" para garantir animações mais suaves.
A política geral de ARR é a seguinte:
- Aprimoramento de toque: quando um evento de toque (
MotionEvent.ACTION_DOWN
) é detectado, a taxa de atualização é aumentada para "Alta" por algum tempo depois que o toque é liberado para manter a capacidade de resposta. - Gestos de movimento rápido: os gestos de movimento rápido são processados de maneira diferente. A taxa de atualização diminui gradualmente à medida que a velocidade de movimento rápido diminui. Confira detalhes sobre esse comportamento na seção Melhoria do rolagem.
- Tela inicial do app e transições de janela: a taxa de atualização também é aumentada por algum tempo durante a inicialização do app, a inicialização da janela e as transições de janela para garantir uma experiência visual suave.
- Animações: animações que envolvem mudanças de movimento ou tamanho recebem automaticamente uma taxa de atualização mais alta para melhorar a fluidez quando a posição ou o tamanho de uma visualização muda.
SurfaceView
eTextureView
: as taxas de frames definidas explicitamente paraTextureView
eSurfaceView
são respeitadas e aplicadas de maneira adequada.
Ativar e desativar o aumento do toque
É possível ativar e/ou desativar o reforço de toque no nível Window
. Por padrão,
quando um usuário toca e tira o dedo da tela, a taxa de renderização
aumenta por algum tempo. As APIs setFrameRateBoostOnTouchEnabled()
e
getFrameRateBoostOnTouchEnabled()
permitem que você impeça que a taxa de
renderização aumente quando um Window
específico é tocado.
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()
Melhoria na rolagem
Um dos principais casos de uso para otimizar a taxa de frames dinamicamente é melhorar a experiência de rolagem (fling). Muitos aplicativos dependem muito de usuários que deslizam para cima para conferir novos conteúdos. O aprimoramento de rolagem de ARR ajusta dinamicamente a taxa de atualização à medida que o gesto de movimento rápido diminui, reduzindo gradualmente a taxa de frames. Isso oferece uma renderização mais eficiente, mantendo a rolagem suave.
Essa melhoria se aplica especificamente a componentes de interface roláveis, incluindo
ScrollView
, ListView
e GridView
, e pode não estar
disponível para todas as implementações personalizadas.
O recurso de rolagem de ARR está disponível para RecyclerView
e
NestedScrollView
. Para ativar esse recurso no app, faça upgrade para as versões
mais recentes de AndroidX.recyclerview
e AndroidX.core
. Consulte a tabela abaixo
para mais detalhes.
Biblioteca |
Versão |
|
1.4.0 |
|
1.15.0 |
Definir as informações de velocidade
Se você tiver um componente rolável personalizado e quiser aproveitar o
recurso de rolagem, chame setFrameContentVelocity()
em cada frame durante
a rolagem suave ou o deslizamento rápido. Confira o snippet de código a seguir como exemplo:
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 mais exemplos, consulte RecyclerView
e
ScrollView
. Para definir a velocidade corretamente, calcule a
velocidade do conteúdo (pixels por segundo) manualmente se as informações necessárias não puderem
ser obtidas de Scroller
ou
OverScroller
.
Se setFrameContentVelocity()
e
getFrameContentVelocity()
forem chamados em visualizações que não são componentes roláveis,
eles não terão nenhum efeito, já que o movimento aciona automaticamente uma
taxa de frames aumentada com base na política atual.
As informações de velocidade são cruciais para ajustar a taxa de renderização. Por exemplo, considere o gesto de deslizar. No início, a velocidade de um movimento rápido pode ser alta, exigindo uma taxa de renderização mais alta para garantir avidez. À medida que o gesto progride, a velocidade diminui, permitindo que a taxa de renderização seja reduzida.
Ativar e desativar o ARR
O ARR é ativado por padrão para melhorar a eficiência energética. É possível desativar esse recurso, mas isso não é recomendado, porque o app vai consumir mais energia. Só considere desativar esse recurso se você encontrar problemas que afetem significativamente a experiência do usuário.
Para ativar ou desativar o ARR, use a
API setFrameRatePowerSavingsBalanced()
em um Window
ou a
API isFrameRatePowerSavingsBalanced()
no arquivo styles.xml
.
O snippet a seguir mostra como ativar ou desativar a ARR em um 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 desativar o ARR pelo arquivo styles.xml
, adicione o
seguinte item ao estilo em res/values/styles.xml
:
<style name="frameRatePowerSavingsBalancedDisabled">
<item name="android:windowIsFrameRatePowerSavingsBalanced">false</item>
</style>