Khi một ảnh động được bắt đầu trong Android, màn hình thường tăng lên tốc độ làm mới tối đa để đảm bảo trải nghiệm mượt mà. Đối với các ảnh động nhỏ như thanh tiến trình và trình trực quan hoá âm thanh, tốc độ làm mới cao này là không cần thiết và dẫn đến mức tiêu thụ điện năng cao.
Kể từ Android 15, nhờ tính năng tốc độ làm mới thích ứng (ARR), các thiết bị đã bật tính năng này có thể giảm thời gian duy trì tốc độ làm mới cao theo 2 cách:
- Với các chế độ tối ưu hoá mới về quản lý tốc độ khung hình của nền tảng, theo mặc định, các ứng dụng có thể kết xuất ở tốc độ khung hình thấp hơn và chỉ tăng lên tốc độ khung hình cao khi cần thiết.
- Tốc độ làm mới màn hình linh động khớp với tốc độ kết xuất nội dung mà không bị giật.
Mặc dù hầu hết các ứng dụng đều được hưởng lợi từ ARR mà không cần sửa đổi, nhưng bạn cũng có thể ghi đè hành vi tốc độ khung hình mặc định nếu cần.
Trang này mô tả những nội dung sau:
- Cách xác định tốc độ khung hình của mỗi Khung hiển thị.
- Chính sách chung về cách ARR xác định tốc độ khung hình được đặt.
- Cách bạn có thể ghi đè hành vi mặc định của tốc độ khung hình theo cách thủ công.
Cơ chế bỏ phiếu của View
Trong hệ thống Khung hiển thị của Android, mỗi Khung hiển thị trong hệ phân cấp giao diện người dùng đều có thể thể hiện tốc độ khung hình ưu tiên. Những lựa chọn ưu tiên này được thu thập và kết hợp để xác định tốc độ khung hình cuối cùng cho mỗi khung hình. Điều này đạt được thông qua cơ chế bỏ phiếu, trong đó mỗi Lượt xem bỏ phiếu dựa trên thuộc tính tốc độ khung hình của lượt xem đó, có thể là một danh mục hoặc một tốc độ cụ thể. Các khung hiển thị thường bình chọn khi được vẽ hoặc cập nhật. Các phiếu bầu này được kết hợp để xác định tốc độ khung hình cuối cùng, sau đó được gửi đến lớp cấp thấp hơn dưới dạng gợi ý để kết xuất.
Hiện tại, hầu hết các Khung hiển thị đều mặc định ở tốc độ khung hình "Bình thường", thường được đặt thành 60 Hz. Để có tốc độ khung hình cao hơn, bạn có thể sử dụng các API cụ thể để tuỳ chỉnh lựa chọn ưu tiên, trong đó hệ thống thường chọn tốc độ khung hình cao nhất. Để biết thêm thông tin về cách sử dụng các API này, hãy xem phần Đặt tốc độ khung hình hoặc danh mục. Các chính sách chung liên quan đến tốc độ khung hình được mô tả trong phần Chính sách chung về ARR.
Danh mục tốc độ khung hình
Trong lớp View
, có nhiều danh mục tốc độ khung hình có thể được dùng trong cuộc bỏ phiếu. Sau đây là nội dung mô tả của từng danh mục:
REQUESTED_FRAME_RATE_CATEGORY_DEFAULT
: Bạn có thể đặt giá trị này để quay lại hành vi mặc định, cho biết View này không có dữ liệu cho tốc độ khung hình.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE
: Khung hiển thị sẽ không ảnh hưởng rõ ràng đến tốc độ khung hình. Điều này có nghĩa là ngay cả khi View đang hoạt động, khung sẽ không xem xét View đó khi xác định tốc độ khung hìnhREQUESTED_FRAME_RATE_CATEGORY_NORMAL
: Cho biết tốc độ khung hình trung bình, phù hợp với những ảnh động không yêu cầu tốc độ khung hình cao hơn hoặc không được hưởng lợi từ độ mượt cao. Tần số này thường là 60 Hz hoặc gần với tần số này.REQUESTED_FRAME_RATE_CATEGORY_HIGH
: Cho biết tốc độ khung hình phù hợp với những ảnh động yêu cầu tốc độ khung hình cao, có thể tăng độ mượt nhưng cũng có thể tăng mức tiêu thụ điện năng.
Một Chế độ xem chỉ bỏ phiếu nếu cần vẽ lại. Tốc độ khung hình cuối cùng được xác định bằng số phiếu bầu cao nhất. Ví dụ: nếu tất cả các phiếu bầu đều là "Bình thường", thì "Bình thường" sẽ được chọn. Khi cả lượt bình chọn "Bình thường" và "Cao" đều xuất hiện, hệ thống sẽ chọn "Cao".
Tốc độ khung hình
Ngoài các danh mục tốc độ khung hình, View cũng có thể chỉ định tốc độ khung hình ưu tiên, chẳng hạn như 30, 60 hoặc 120 Hz. Khi có nhiều lượt bình chọn tốc độ khung hình, tốc độ khung hình cuối cùng sẽ được xác định theo các quy tắc sau:
- Bội số của nhau: Nếu tốc độ khung hình được bình chọn là bội số của nhau, thì giá trị cao nhất sẽ được chọn. Ví dụ: nếu có 2 lượt bình chọn – 30 Hz và 90 Hz – thì 90 Hz sẽ được chọn làm tốc độ khung hình cuối cùng.
- Không phải là bội số của nhau:
- Nếu có phiếu bầu nào lớn hơn 60 Hz, thì phiếu bầu đó sẽ được tính là "Cao".
- Nếu tất cả phiếu bầu đều là 60 Hz trở xuống, thì đó được coi là phiếu bầu "Bình thường".
Ngoài ra, nếu có cả giá trị tốc độ khung hình và danh mục tốc độ khung hình, thì giá trị cao hơn thường sẽ xác định tốc độ kết xuất cuối cùng. Ví dụ: khi kết hợp giữa một phiếu bầu 60 Hz và một phiếu bầu "Cao", hoặc một phiếu bầu 120 Hz và một phiếu bầu "Bình thường", tốc độ kết xuất thường sẽ được đặt thành 120 Hz.
Ngoài các phiếu bầu từ một ứng dụng, cũng có thể có những gợi ý khác được gửi đến lớp cấp thấp hơn từ các thành phần khác nhau trong cùng một khung hình. Nhiều thành phần trong số này có thể bắt nguồn từ các thành phần trên giao diện người dùng của hệ thống, chẳng hạn như bảng thông báo, thanh trạng thái, thanh điều hướng và các thành phần khác. Giá trị tốc độ khung hình cuối cùng được xác định dựa trên phiếu bầu của nhiều thành phần.
Đặt tốc độ khung hình hoặc danh mục
Trong một số trường hợp, bạn có thể có tốc độ khung hình ưu tiên cho một Khung hiển thị. Ví dụ: bạn có thể đặt tốc độ khung hình ưu tiên thành "Cao" cho một View để tăng tốc độ khung hình nếu một ảnh động xuất hiện không mượt mà. Ngoài ra, nếu có ảnh động tĩnh hoặc chạy chậm trên video (thường phát ở tốc độ 24 hoặc 30 Hz), bạn có thể muốn ảnh động chạy ở tốc độ thấp hơn "Bình thường" để giảm mức tiêu thụ điện.
Bạn có thể dùng API setRequestedFrameRate()
và getRequestedFrameRate()
để chỉ định tốc độ khung hình hoặc danh mục ưu tiên của một Khung hiển thị nhất định.
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);
Để biết ví dụ về cách sử dụng, hãy xem TextureView
.
Chính sách chung về ARR
Ở phần trước, chúng ta đã thảo luận về việc hầu hết các ảnh động đều được hiển thị ở tốc độ 60 Hz theo mặc định, vì mỗi View đều có "Normal" được đặt làm tốc độ khung hình ưu tiên. Tuy nhiên, có những trường hợp tốc độ khung hình được tăng lên "Cao" để đảm bảo ảnh động mượt mà hơn.
Chính sách chung về ARR như sau:
- Tăng cường cảm ứng: Khi một sự kiện chạm (
MotionEvent.ACTION_DOWN
) được phát hiện, tốc độ làm mới sẽ được tăng lên "Cao" trong một khoảng thời gian sau khi thao tác chạm được thả ra để duy trì khả năng phản hồi. - Cử chỉ hất: Cử chỉ hất được xử lý theo cách khác – tốc độ làm mới giảm dần khi vận tốc hất chậm lại. Bạn có thể xem thông tin chi tiết về hành vi này trong phần Cải thiện thao tác cuộn.
- Khởi chạy ứng dụng và chuyển đổi cửa sổ: Tốc độ làm mới cũng được tăng lên trong một khoảng thời gian khi khởi chạy ứng dụng, khởi tạo cửa sổ và chuyển đổi cửa sổ để đảm bảo trải nghiệm hình ảnh mượt mà.
- Ảnh động: Ảnh động có chuyển động hoặc thay đổi kích thước sẽ tự động nhận được tốc độ làm mới cao hơn để tăng độ mượt khi vị trí hoặc kích thước của một Thành phần hiển thị thay đổi.
SurfaceView
vàTextureView
: Tốc độ khung hình được đặt rõ ràng choTextureView
vàSurfaceView
sẽ được tuân thủ và áp dụng cho phù hợp.
Bật và tắt tính năng tăng cường cảm ứng
Bạn có thể bật và/hoặc tắt tính năng tăng cường cảm ứng ở cấp Window
. Theo mặc định, khi người dùng chạm và nhấc ngón tay khỏi màn hình, tốc độ kết xuất sẽ tăng trong một khoảng thời gian. Các API setFrameRateBoostOnTouchEnabled()
và getFrameRateBoostOnTouchEnabled()
cho phép bạn ngăn tốc độ kết xuất tăng lên khi một Window
cụ thể được chạm vào.
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()
Cải thiện thao tác cuộn
Một trường hợp sử dụng chính để tối ưu hoá tốc độ khung hình một cách linh động là cải thiện trải nghiệm cuộn (hất). Nhiều ứng dụng phụ thuộc rất nhiều vào việc người dùng vuốt lên để xem nội dung mới. Tính năng cải tiến thao tác cuộn ARR sẽ điều chỉnh tốc độ làm mới một cách linh hoạt khi cử chỉ hất giảm tốc độ, từ đó giảm dần tốc độ khung hình. Điều này giúp hiển thị hiệu quả hơn trong khi vẫn duy trì thao tác cuộn mượt mà.
Điểm cải tiến này áp dụng riêng cho các thành phần giao diện người dùng có thể cuộn, bao gồm ScrollView
, ListView
và GridView
, đồng thời có thể không dùng được cho tất cả các cách triển khai tuỳ chỉnh.
Tính năng cuộn ARR có trên RecyclerView
và NestedScrollView
. Để bật tính năng này trong ứng dụng, hãy nâng cấp lên phiên bản mới nhất của AndroidX.recyclerview
và AndroidX.core
. Hãy xem bảng sau để biết thông tin chi tiết.
Thư viện |
Phiên bản |
|
1.4.0 |
|
1.15.0 |
Đặt thông tin vận tốc
Nếu bạn có một thành phần có thể cuộn tuỳ chỉnh và muốn tận dụng tính năng cuộn, hãy gọi setFrameContentVelocity()
trên mọi khung hình trong khi cuộn hoặc hất nhẹ. Hãy xem đoạn mã sau đây để biết ví dụ:
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()
Để xem thêm ví dụ, hãy xem RecyclerView
và ScrollView
. Để đặt vận tốc chính xác, hãy tính vận tốc nội dung (pixel mỗi giây) theo cách thủ công nếu bạn không thể lấy thông tin cần thiết từ Scroller
hoặc OverScroller
.
Xin lưu ý rằng nếu setFrameContentVelocity()
và getFrameContentVelocity()
được gọi trên các thành phần View không thể cuộn, thì chúng sẽ không có hiệu lực vì chuyển động sẽ tự động kích hoạt tốc độ khung hình tăng lên dựa trên chính sách hiện tại.
Thông tin về vận tốc là yếu tố quan trọng để điều chỉnh tốc độ kết xuất. Ví dụ: hãy xem xét cử chỉ hất. Ban đầu, vận tốc của thao tác hất có thể cao, do đó cần có tốc độ kết xuất cao hơn để đảm bảo độ mượt. Khi cử chỉ tiến triển, vận tốc sẽ giảm, cho phép giảm tốc độ kết xuất.
Bật và tắt ARR
ARR được bật theo mặc định để tăng hiệu suất sử dụng điện. Mặc dù bạn có thể tắt tính năng này, nhưng không nên làm như vậy vì ứng dụng sẽ tiêu thụ nhiều pin hơn. Bạn chỉ nên cân nhắc việc tắt tính năng này nếu gặp phải các vấn đề ảnh hưởng đáng kể đến trải nghiệm người dùng.
Để bật hoặc tắt ARR, hãy sử dụng API setFrameRatePowerSavingsBalanced()
trên Window
hoặc sử dụng API isFrameRatePowerSavingsBalanced()
thông qua tệp styles.xml
.
Đoạn mã sau đây cho biết cách bật hoặc tắt ARR trên 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()
Để tắt ARR thông qua tệp styles.xml
, hãy thêm mục sau vào kiểu của bạn trong res/values/styles.xml
:
<style name="frameRatePowerSavingsBalancedDisabled">
<item name="android:windowIsFrameRatePowerSavingsBalanced">false</item>
</style>
ARR cho Compose
Compose 1.9 cũng bổ sung tính năng hỗ trợ tốc độ làm mới thích ứng.
Trong hệ thống Khung hiển thị, bạn sử dụng phương thức setRequestedFrameRate()
để yêu cầu một tốc độ khung hình cụ thể cho một Khung hiển thị. Trong Compose, một đối tượng sửa đổi mới cho phép bạn chỉ định tốc độ khung hình cho một thành phần kết hợp. Đối tượng sửa đổi này hoạt động tương tự như setRequestedFrameRate()
, chấp nhận giá trị tốc độ khung hình dương (tính bằng Hz) hoặc một danh mục tốc độ khung hình được xác định trước, FrameRateCategory
.
Chữ ký cho các API như sau:
Modifier.preferredFrameRate(frameRate: Float)
Modifier.preferredFrameRate(frameRateCategory: FrameRateCategory)
Trong đoạn mã dưới đây, đối tượng sửa đổi tốc độ khung hình mới (Modifier.requestedFrameRate(120f))
được áp dụng cho một thành phần kết hợp Text
. Đối tượng sửa đổi này khiến thành phần kết hợp Text
yêu cầu tốc độ khung hình ưu tiên là 120 khi được vẽ hoặc tạo ảnh động (ví dụ: với các thay đổi về độ mờ):
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
)
}
Sau đó, tốc độ khung hình ưu tiên từ tất cả các thành phần kết hợp sẽ được thu thập và hợp nhất để xác định tốc độ khung hình cuối cùng cho mỗi khung hình. Để biết thêm thông tin chi tiết, hãy xem SetFrameRateSample
và SetFrameRateCategorySample
.