在 Android 中启动动画时,显示屏通常会提升到最高刷新率以确保流畅体验。对于进度条和音频可视化工具等小型动画,如此高的刷新率是不必要的,并且会导致高功耗。
从 Android 15 开始,借助自适应刷新率 (ARR) 功能,支持该功能的设备可以在两个方面减少高刷新率的驻留时间:
- 借助新的平台帧速率管理优化,应用默认可以在较低帧速率下渲染,仅在必要时才提升到较高帧速率。
- 显示刷新率动态匹配内容渲染速率,无卡顿现象。
虽然大多数应用应该在不进行任何修改的情况下受益于 ARR,但您也可以根据需要覆盖默认帧速率行为。
本页介绍以下内容:
- 每个 View 的帧速率如何确定。
- ARR 如何确定帧速率设置的总体策略。
- 如何手动覆盖默认帧速率行为。
View 投票机制
在 Android 的 View 系统中,UI 层级结构中的每个 View 都可以表达其偏好的帧速率。系统会收集并组合这些偏好设置,以确定每一帧的最终帧速率。这是通过一种投票机制实现的,其中每个 View 根据其帧速率属性(可以是类别或特定速率)进行投票。View 通常在绘制或更新时进行投票。这些投票会合并以确定最终帧速率,然后作为渲染提示发送到较低层。
目前,大多数 View 默认采用“普通”帧速率,通常设置为 60 Hz。对于更高的帧速率,您可以使用特定的 API 自定义偏好设置,系统通常会选择最高的帧速率。有关使用这些 API 的更多信息,请参阅设置帧速率或类别部分。关于帧速率的总体策略在通用 ARR 策略部分中描述。
帧速率类别
在 View
类中,有不同的帧速率类别可用于投票。每个类别的描述如下:
REQUESTED_FRAME_RATE_CATEGORY_DEFAULT
:此值可以设置为返回默认行为,表示此 View 没有关于帧速率的数据。REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE
:View 将明确不影响帧速率。这意味着即使 View 处于活动状态,框架在确定帧速率时也不会考虑它。REQUESTED_FRAME_RATE_CATEGORY_NORMAL
:表示适用于不需要更高帧速率或不需要高平滑度的动画的中等帧速率。这通常是 60 Hz 或接近此频率。REQUESTED_FRAME_RATE_CATEGORY_HIGH
:表示适用于需要高帧速率的动画的帧速率,这可能会提高平滑度,但也可能增加电量消耗。
View 仅在需要重绘时投票。最终帧速率由最高的投票决定。例如,如果所有投票都是“普通”,则选择“普通”。如果同时出现“普通”和“高”投票,则选择“高”。
帧速率
除了帧速率类别外,View 还可以指定偏好的帧速率,例如 30、60 或 120 Hz。当有多个帧速率投票时,最终帧速率由以下规则确定:
- 互为倍数:如果投票的帧速率互为倍数,则选择最高值。例如,如果有两个投票 - 30 Hz 和 90 Hz - 则 90 Hz 将被选为最终帧速率。
- 不互为倍数:
- 如果任何投票高于 60 Hz,则视为“高”投票。
- 如果所有投票都是 60 Hz 或更低,则视为“普通”投票。
此外,如果同时存在帧速率值和帧速率类别,则通常由较高的值决定最终的渲染速率。例如,如果同时有 60 Hz 投票和“高”投票,或 120 Hz 投票和“普通”投票,则渲染速率通常会设置为 120 Hz。
除了应用中的投票之外,同一帧中来自不同组件的提示也可能发送到较低层。其中许多可能源自系统 UI 组件,例如通知栏、状态栏、导航栏等。最终帧速率值是根据多个组件的投票决定的。
设置帧速率或类别
在某些情况下,您可能对 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 策略
在上一节中,我们讨论了大多数动画默认以 60 Hz 显示,因为每个 View 都将“普通”设置为偏好帧速率。但是,在某些情况下会例外,将帧速率提高到“高”,以确保更流畅的动画。
通用 ARR 策略如下:
- 触控提升:检测到触控事件(
MotionEvent.ACTION_DOWN
)时,触控释放后的一段时间内,刷新率会提升到“高”,以保持响应速度。 - 抛掷手势:抛掷手势的处理方式不同——刷新率会随着抛掷速度的减慢而逐渐降低。您可以在滚动改进部分找到有关此行为的详细信息。
- 应用启动和窗口过渡:在应用启动、窗口初始化和窗口过渡期间,刷新率也会提升一段时间,以确保流畅的视觉体验。
- 动画:涉及移动或尺寸变化的动画会自动获得更高的刷新率,以提高 View 位置或尺寸变化时的平滑度。
SurfaceView
和TextureView
:帧速率为TextureView
和SurfaceView
明确设置的帧速率会得到遵守并相应应用。
启用和禁用触控提升
您可以在 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()
滚动改进
动态优化帧速率的一个关键用例是改进滚动(抛掷)体验。许多应用 heavily 依赖用户向上滑动以查看新内容。ARR 滚动增强功能会在抛掷手势减速时动态调整刷新率,逐步降低帧速率。这提供了更高效的渲染,同时保持了流畅的滚动。
此改进功能特别适用于可滚动的 UI 组件,包括 ScrollView
、ListView
和 GridView
,并且可能不适用于所有自定义实现。
ARR 滚动功能适用于 RecyclerView
和 NestedScrollView
。要在您的应用中启用此功能,请升级到最新版本的 AndroidX.recyclerview
和 AndroidX.core
。有关详细信息,请参阅下表。
库 |
版本 |
|
1.4.0 |
|
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()
有关更多示例,请参阅 RecyclerView
和 ScrollView
。要正确设置速度,如果无法从 Scroller
或 OverScroller
获取所需信息,请手动计算内容速度(像素/秒)。
请注意,如果在非可滚动组件的 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>