使用自适应刷新率优化帧速率

在 Android 中启动动画时,显示屏通常会提升到最大刷新率,以确保流畅的体验。对于进度条和音频可视化器等小动画,这种高刷新率是没有必要的,并且会导致功耗高。

从 Android 15 开始,借助自适应刷新率 (ARR) 功能,启用该功能的设备可以在以下两个方面减少高刷新率驻留时间:

  • 借助新的平台帧速率管理优化,应用默认以较低的帧速率渲染,仅在必要时才会提升到高帧速率。
  • 显示屏刷新率会动态匹配内容呈现速率,不会出现卡顿。

虽然大多数应用无需进行任何修改即可受益于 ARR,但您也可以根据需要替换默认帧速率行为。

本页介绍以下内容:

  • 如何确定每个 View 的帧速率。
  • 有关 ARR 如何确定帧速率设置的一般政策。
  • 如何手动替换默认帧速率行为。

View 投票机制

在 Android 的 View 系统中,界面层次结构中的每个 View 都可以表达其首选帧速率。系统会收集并组合这些偏好设置,以确定每个帧的最终帧速率。这通过投票机制实现,其中每个 View 都会根据其帧速率属性(可以是类别或特定速率)进行投票。视图通常会在绘制或更新时进行投票。这些投票会合并以确定最终帧速率,然后将其发送到较低级别的层作为渲染提示。

目前,大多数 View 的默认帧速率为“正常”,通常设为 60 Hz。如需更高的帧速率,您可以使用特定 API 自定义偏好设置,系统通常会选择最高帧速率。如需详细了解如何使用这些 API,请参阅设置帧速率或类别部分。一般 ARR 政策部分介绍了有关帧速率的一般政策。

帧速率类别

View 类中,有不同的帧速率类别可用于投票。各个类别的说明如下:

只有当 View 需要重新绘制时,才会进行投票。最终帧速率由得票数最高的帧速率决定。例如,如果所有投票结果均为“正常”,则系统会选择“正常”。如果同时出现“Normal”(正常)和“High”(高)投票,系统会选择“High”。

帧速率

除了帧速率类别之外,View 还可以指定首选帧速率,例如 30、60 或 120 Hz。如果投出了多个帧速率选票,最终帧速率将由以下规则决定:

  • 彼此为倍数:如果投票选出的帧速率彼此为倍数,则系统会选择最高值。例如,如果有两个投票选项(30 Hz 和 90 Hz),则系统会选择 90 Hz 作为最终帧速率。
  • 不是彼此的倍数
    • 如果任何投票结果大于 60 Hz,则计为“高”。
    • 如果所有投票结果均低于 60 Hz,则计为“正常”投票。

此外,如果同时使用帧速率值和帧速率类别,则通常以较高值确定最终呈现速率。例如,如果投票结果为 60 Hz 和“高”或 120 Hz 和“正常”,则渲染速率通常会设置为 120 Hz。

除了应用的投票之外,同一帧中的不同组件可能还会向更低级别的层发送其他提示。其中许多问题都可能源自系统界面组件,例如通知栏、状态栏、导航栏等。最终的帧速率值是根据多个组件的投票结果确定的。

设置帧速率或类别

在某些情况下,您可能需要为 View 指定首选帧速率。例如,如果动画看起来不流畅,您可以将 View 的首选帧速率设置为“高”,以提高帧速率。此外,如果视频上有缓慢或静态动画(通常以 24 或 30 Hz 播放),您可能希望动画以低于“正常”的速率运行,以降低功耗。

您可以使用 setRequestedFrameRate()getRequestedFrameRate() API 指定给定 View 的首选帧速率或类别。

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);

如需查看使用示例,请参阅 TextureView

一般 ARR 政策

在上一节中,我们讨论过,由于每个 View 都将“Normal”设置为首选帧速率,因此大多数动画默认以 60 Hz 的速率显示。不过,在某些例外情况下,系统会将帧速率提高到“高”,以确保动画更流畅。

一般 ARR 政策如下:

  • 触摸提速:检测到触摸事件 (MotionEvent.ACTION_DOWN) 后,在用户松开触摸操作后,刷新率会提升到“高”一段时间,以保持响应能力。
  • 快速滑动手势:系统会以不同的方式处理快速滑动手势,随着快速滑动速度的减慢,刷新率会逐渐降低。如需详细了解此行为,请参阅滚动改进部分。
  • 应用启动和窗口转换:在应用启动、窗口初始化和窗口转换期间,刷新率也会在一定时间内提升,以确保流畅的视觉体验。
  • 动画:涉及移动或大小更改的动画会自动获得更高的刷新率,以便在视图的位置或大小发生变化时提高流畅度。
  • SurfaceViewTextureView:系统会遵循为 TextureViewSurfaceView 明确设置的帧速率,并相应地应用这些帧速率。

启用和停用触控提升功能

您可以在 Window 级别启用和/或停用轻触增强功能。默认情况下,当用户轻触屏幕并将手指从屏幕上移开时,渲染速率会在短时间内提高。借助 setFrameRateBoostOnTouchEnabled()getFrameRateBoostOnTouchEnabled() API,您可以防止在触摸特定 Window 时渲染速率增加。

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()

滚动功能改进

动态优化帧速率的一个关键用例是改善滚动(快速滑动)体验。许多应用都非常依赖用户向上滑动来查看新内容。ARR 滚动增强功能会随着快速滑动手势的速度减慢而动态调整刷新率,从而逐渐降低帧速率。这样可以实现更高效的渲染,同时保持流畅的滚动。

此项改进专门适用于可滚动界面组件,包括 ScrollViewListViewGridView,可能不适用于所有自定义实现。

ARR 滚动功能适用于 RecyclerViewNestedScrollView。如需在应用中启用此功能,请升级到最新版本的 AndroidX.recyclerviewAndroidX.core。如需了解详情,请参阅下表。

版本

AndroidX.recyclerview

1.4.0

AndroidX.core

1.15.0

设置速度信息

如果您有一个自定义可滚动组件,并且想要利用滚动功能,请在流畅滚动或快速滑动时,对每个帧调用 setFrameContentVelocity()。如需查看示例,请参阅以下代码段:

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()

如需查看更多示例,请参阅 RecyclerViewScrollView。如需正确设置速度,如果无法从 ScrollerOverScroller 获取所需信息,请手动计算内容速度(像素/秒)。

请注意,如果对非可滚动组件的 View 调用 setFrameContentVelocity()getFrameContentVelocity(),则不会产生任何效果,因为移动会根据当前政策自动触发帧速率增加。

速度信息对于调整渲染速率至关重要。例如,请考虑快速滑动手势。在开始时,快速滑动操作的速度可能较高,因此需要更高的渲染速率来确保流畅度。随着手势的进行,速度会降低,从而降低渲染速率。

启用和停用 ARR

ARR 默认处于启用状态,以提高功耗效率。虽然您可以停用此功能,但不建议这样做,因为应用会因此而耗用更多电量。只有在遇到会严重影响用户体验的问题时,才应考虑停用此功能。

如需启用或停用 ARR,请对 Window 使用 setFrameRatePowerSavingsBalanced() API,或通过 styles.xml 文件使用 isFrameRatePowerSavingsBalanced() API。

以下代码段展示了如何在 Window 上启用或停用 ARR:

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()

如需通过 styles.xml 文件停用 ARR,请将以下项添加到 res/values/styles.xml 中的样式中:

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