Frame Rate trong ứng dụng di động — định nghĩa, fps và cách cải thiện

Tác giả: IT Sectr Đã đăng: 2026-03-31 Thời gian đọc: 10 phút

Frame Rate là số khung hình mà hệ thống đồ họa hiển thị trong một giây. Trong các ứng dụng di động, tần số khung hình trực tiếp quyết định độ mượt của hoạt ảnh, cuộn trang và chuyển tiếp giữa các màn hình. Theo Android Developers, 2025, Frame Rate mục tiêu là 60 fps cho màn hình tiêu chuẩn và 120 fps cho thiết bị có tần số quét cao. Sai lệch so với giá trị mục tiêu dẫn đến giật hình và suy giảm trải nghiệm người dùng.

Những điểm chính

  • Frame Rate — số khung hình trên giây (fps) quyết định độ mượt của giao diện người dùng.
  • Frame Rate mục tiêu tiêu chuẩn là 60 fps, tương ứng với 16,6 ms mỗi khung hình.
  • Thiết bị có màn hình 120 Hz yêu cầu 120 fps (8,3 ms mỗi khung hình).
  • Các khung hình bị bỏ lỡ gây ra Jank — hiện tượng giật hình đáng chú ý trong hoạt ảnh.
  • Hồ sơ Frame Rate là bước đầu tiên để tối ưu hóa hiệu suất giao diện người dùng.

Frame Rate là gì

Frame Rate (tần số khung hình) là một chỉ số được đo bằng khung hình trên giây (fps) cho biết ứng dụng cập nhật hình ảnh trên màn hình bao nhiêu lần mỗi giây. Mắt người cảm nhận chuyển động là mượt mà từ 24 fps (điện ảnh), nhưng giao diện tương tác yêu cầu ít nhất 60 fps để các thao tác chạm và hoạt ảnh cảm thấy tức thì. Mỗi khung hình là một chu kỳ hoàn chỉnh: xử lý đầu vào người dùng, tính toán Bố cục, kết xuất hệ thống phân cấp View và xuất ra màn hình. Nếu bất kỳ giai đoạn nào vượt quá ngân sách thời gian được phân bổ (16,6 ms ở 60 fps), khung hình sẽ bị bỏ qua và người dùng thấy giật hình.

Điều quan trọng là phân biệt Frame Rate của ứng dụng với tần số quét của màn hình (Refresh Rate). Tần số quét là đặc tính phần cứng của màn hình: số lần màn hình cập nhật hình ảnh vật lý mỗi giây (60, 90, 120 hoặc 144 Hz). Frame Rate là số khung hình mỗi giây mà ứng dụng kết xuất được. Nếu ứng dụng xuất ra 60 fps trên màn hình 120 Hz, mỗi khung hình thứ hai sẽ bị trùng lặp — hình ảnh vẫn mượt nhưng không phản hồi nhanh như có thể. Theo Google I/O 2023, các flagship hiện đại có thể duy trì 120 fps trong các kịch bản giao diện đơn giản, nhưng dưới tải nặng (trò chơi, danh sách phức tạp) tần số giảm xuống 40–60 fps.

Kết xuất khung hình hoạt động như thế nào

Kết xuất khung hình trong ứng dụng di động trải qua một đường ống gồm nhiều giai đoạn. Trong Android, đường ống bao gồm: xử lý đầu vào (Input), hoạt ảnh (Animation), đo lường và sắp xếp (Layout), vẽ (Draw), đồng bộ hóa GPU và xuất màn hình (Swap). Mỗi giai đoạn chạy trên CPU hoặc GPU và tổng thời gian của tất cả các giai đoạn không được vượt quá ngân sách khung hình. Đối với 60 fps, ngân sách là 16,6 ms, đối với 120 fps — 8,3 ms. Choreographer (Android) và CADisplayLink (iOS) đồng bộ hóa kết xuất với khoảng chặn dọc của màn hình (VSync), đảm bảo khung hình chỉ được xuất ra tại thời điểm làm mới màn hình, tránh xé hình.

Trong iOS, đường ống tương tự: Run Loop xử lý sự kiện, Core Animation tính toán các lớp, Render Server (một tiến trình riêng biệt) kết xuất và gửi khung hình đến GPU. Sự khác biệt trong iOS là tiến trình Render Server chuyên dụng, cách ly kết xuất khỏi ứng dụng chính. Nếu ứng dụng chặn luồng chính, Render Server vẫn có thể vẽ khung hình cuối cùng đã biết, nhưng hoạt ảnh sẽ dừng lại. Nếu bản thân Render Server không theo kịp — GPU nhàn rỗi và Frame Rate giảm. Theo Apple WWDC 2022, nguyên nhân phổ biến nhất của Frame Rate thấp trong iOS là lồng ghép CALayer quá mức, shadowPath nặng và kết xuất ngoài màn hình.

Theo dõi khung hình qua Choreographer

Mã Kotlin đăng ký Choreographer.FrameCallback và ghi lại thời gian thực tế giữa các khung hình. Nếu khoảng thời gian vượt quá 16,6 ms, một khung hình bị bỏ lỡ được ghi lại.

kotlin
class FrameRateMonitor {

    private var lastFrameTime = 0L
    private val frameCallback =
        Choreographer.FrameCallback { frameTimeNanos ->
            if (lastFrameTime != 0L) {
                val deltaMs = (frameTimeNanos - lastFrameTime) / 1_000_000f
                if (deltaMs > 16.6f) {
                    Log.w("FrameRate",
                        "Skipped frame: $deltaMs ms")
                }
            }
            lastFrameTime = frameTimeNanos
            Choreographer.getInstance()
                .postFrameCallback(this)
        }

    fun start() {
        Choreographer.getInstance()
            .postFrameCallback(frameCallback)
    }
}

Tần số quét màn hình và Frame Rate

Tần số quét (Refresh Rate) là một đặc tính phần cứng của màn hình xác định số lần màn hình vẽ lại hình ảnh vật lý mỗi giây. Màn hình tiêu chuẩn có 60 Hz, flagship hiện đại có 90, 120 hoặc 144 Hz. Frame Rate của ứng dụng có thể thấp hơn, bằng hoặc cao hơn tần số quét (trong trường hợp sau, các khung hình dư thừa sẽ bị loại bỏ). Kịch bản lý tưởng là khi Frame Rate khớp với Refresh Rate: mỗi chu kỳ phần cứng nhận được một khung hình mới từ ứng dụng và chuyển động mượt mà tối đa. Nếu Frame Rate thấp hơn, màn hình lặp lại khung hình cuối cùng, được cảm nhận như vi giật.

Android và iOS hỗ trợ chuyển đổi tần số quét động. Android 12+ sử dụng Smart Refresh Rate: khi cuộn, hệ thống tăng tần số lên 120 Hz, trên nội dung tĩnh giảm xuống 60 Hz để tiết kiệm pin. iOS ProMotion (iPhone 13 Pro trở lên) hoạt động tương tự — tần số thay đổi từ 10 đến 120 Hz tùy theo nội dung. Nhà phát triển nên kiểm tra xem thiết bị có hỗ trợ tần số cao không và điều chỉnh ngân sách thời gian cho mỗi khung hình. Nếu ứng dụng không thể kết xuất khung hình trong 8,3 ms (cho 120 Hz), tốt hơn nên ép xuống 60 Hz — điều này sẽ đảm bảo Frame Rate ổn định mà không bỏ lỡ khung hình.

Loại màn hìnhTần số quétNgân sách mỗi khungThiết bị
Tiêu chuẩn60 Hz16,6 msHầu hết Android/iOS
Cao90 Hz11,1 msOnePlus, Pixel 6+
Flagship120 Hz8,3 msiPhone Pro, Galaxy S22+
Chơi game144 Hz6,9 msROG Phone, Nubia RedMagic

Công cụ đo lường Frame Rate

Cả công cụ tích hợp của nền tảng và trình hồ sơ của bên thứ ba đều có sẵn để đo Frame Rate trong ứng dụng di động. Trong Android, công cụ chính là GPU Profiling (Developer Options → Profile GPU Rendering), hiển thị dòng thời gian của mỗi khung hình được phân chia theo các giai đoạn (Draw, Prepare, Process, Execute). Phân tích chi tiết hơn được cung cấp bởi Android Studio Profiler — nó ghi lại hồ sơ kết xuất đầy đủ cho biết các Chế độ xem cụ thể gây ra việc vẽ lại. Trong iOS, Instruments với mẫu Core Animation được sử dụng — nó hiển thị FPS, thời gian kết xuất lớp và số lần kết xuất ngoài màn hình.

Để giám sát Frame Rate trong sản xuất, Firebase Performance (Android) được sử dụng — nó thu thập Frame Rate trong nền và tổng hợp theo thiết bị, phiên bản hệ điều hành và phiên. Trong iOS, MetricKit cung cấp dữ liệu tương tự qua MXAnimatoryMetric. Đối với trò chơi và ứng dụng Flutter, FrameTimingCallback (Flutter) và Unity Profiler được sử dụng. Điều quan trọng là đo không phải Frame Rate trung bình mà là phần trăm: P50, P90 và P99. Một ứng dụng có thể hiển thị trung bình 55 fps nhưng có P99 = 30 fps — điều này có nghĩa là 1% thời gian người dùng thấy giật hình nghiêm trọng, đủ để đánh giá tiêu cực.

Đo Frame Rate trong Flutter

Ví dụ Dart cho thấy cách đăng ký FrameTimingCallback trong Flutter và ghi lại số khung hình bị bỏ lỡ. Callback được kích hoạt sau mỗi khung hình hoàn thành.

dart
import 'package:flutter/scheduler.dart';

class FrameRateLogger {
    int totalFrames = 0;
    int missedFrames = 0;

    void start() {
        SchedulerBinding.instance
            .addTimingsCallback(_onReportTimings);
    }

    void _onReportTimings(List<FrameTiming> timings) {
        for (final timing in timings) {
            totalFrames++;
            if (timing.totalSpan()
                > Duration(milliseconds: 16)) {
                missedFrames++;
            }
        }
        debugPrint("FPS: \${totalFrames - missedFrames}");
    }
}

Tối ưu hóa tần số khung hình

Tối ưu hóa Frame Rate bắt đầu bằng việc xác định các nút thắt cổ chai trong đường ống kết xuất. Ở giai đoạn Bố cục, các vấn đề chính là lồng ghép quá mức hệ thống phân cấp View, sử dụng bố cục tương đối (RelativeLayout với nhiều quy tắc) và các cuộc gọi requestLayout thường xuyên. Giải pháp là sử dụng ConstraintLayout hoặc hệ thống phân cấp phẳng, tránh lồng ghép hơn 5–6 cấp. Ở giai đoạn Vẽ — overdraw: khi một pixel được vẽ nhiều lần trong một khung hình. Ví dụ: nền Activity trắng bên dưới fragment bán trong suốt, bên dưới có thêm một lớp nữa — mỗi pixel được vẽ ba lần. Công cụ Debug GPU Overdraw hiển thị các khu vực có vấn đề bằng mã màu. Khuyến nghị giữ overdraw ở mức 2x hoặc thấp hơn.

Trong iOS, các vấn đề chính là cornerRadiusmasksToBounds nặng — chúng gây ra kết xuất ngoài màn hình, nơi Core Animation tạo bộ đệm tạm thời, vẽ vào đó, sau đó sao chép kết quả lên màn hình. Kết xuất ngoài màn hình dễ dàng phát hiện trong Instruments Core Animation: nếu dòng Renderer màu đỏ — có vấn đề. Giải pháp là sử dụng UIImageView với hình ảnh được cắt sẵn thay vì cornerRadius, tránh groupOpacityshouldRasterize trừ khi thực sự cần thiết. Đối với cả hai nền tảng, việc giảm thiểu số lượng cuộc gọi invalidate()setNeedsDisplay() là rất quan trọng — mỗi cuộc gọi như vậy kích hoạt một chu kỳ vẽ lại toàn bộ view.

Tối ưu hóa hệ thống phân cấp trong Android

Mã trình bày việc thay thế lồng ghép RelativeLayout sâu bằng cấu trúc phẳng với ConstraintLayout. Giảm cấp độ lồng ghép từ 4 xuống 1 giúp giảm thời gian Bố cục 30–50%.

kotlin
// Ví dụ: cấu trúc phẳng qua ConstraintLayout
class OptimizedView(context: Context) :
    ConstraintLayout(context) {

    private val binding =
        ItemProfileBinding.inflate(
            LayoutInflater.from(context)
        )

    fun bind(user: User) {
        binding.avatar.setImageURI(user.avatarUrl)
        binding.nameText.text = user.name
        // ràng buộc dữ liệu mà không vẽ lại toàn bộ container
    }
}

Tần số thích ứng và Dynamic Frame Rate

Các ứng dụng di động hiện đại ngày càng sử dụng Frame Rate thích ứng — một hệ thống tự động điều chỉnh tần số mục tiêu theo kịch bản hiện tại. Cuộn nhanh yêu cầu 120 fps để mượt mà, trong khi màn hình tĩnh chỉ cần 60 fps hoặc thậm chí 30 fps cho video. Trong Android, sự thích ứng được thực hiện qua Choreographer.setFrameInterval (API 33+) và Window.setFrameRate. Nhà phát triển có thể chỉ định tần số ưu tiên: setPreferredRefreshRate trong SurfaceView hoặc setFrameRate trong Window. iOS tự động quản lý tần số qua ProMotion, nhưng nhà phát triển có thể đặt rõ ràng preferredFramesPerSecond cho CADisplayLink.

Dynamic Frame Rate đặc biệt quan trọng đối với trò chơi và ứng dụng có hoạt ảnh. Theo Google, giảm Frame Rate từ 120 xuống 60 Hz trên màn hình tĩnh tiết kiệm đến 30–40% năng lượng GPU. Để đạt được sự cân bằng tốt nhất giữa độ mượt và mức tiêu thụ điện năng, khuyến nghị: đo Frame Rate thực tế trong các kịch bản khác nhau, đặt fps mục tiêu tùy theo cảnh (trò chơi — 60, menu — 30, video — 24) và chuyển đổi chế độ qua các thành phần Lifecycle-aware để ứng dụng không lãng phí tài nguyên khi kết xuất 120 fps trong nền khi bị thu nhỏ.

Đặt Frame Rate ưu tiên

Mã Swift đặt preferredFramesPerSecond cho CADisplayLink trong iOS. Khi cuộn, tần số tăng lên 120 Hz, khi dừng, giảm xuống 60 Hz.

swift
class AdaptiveFrameRateManager {

    private var displayLink: CADisplayLink?

    func startWithHighRate() {
        displayLink = CADisplayLink(
            target: self,
            selector: #selector(step)
        )
        if #available(iOS 15.0, *) {
            displayLink?.preferredFrameRateRange =
                CAFrameRateRange(
                    minimum: 60,
                    maximum: 120,
                    preferred: 120
                )
        }
        displayLink?.add(to: .current,
            forMode: .common)
    }

    @objc
    private func step() {
        // cập nhật hoạt ảnh
    }
}

Câu hỏi thường gặp

Frame Rate bao nhiêu được coi là tốt cho ứng dụng di động?

Đối với ứng dụng di động, Frame Rate mục tiêu là 60 fps (16,6 ms mỗi khung hình). Đối với thiết bị có màn hình 120 Hz, nên đạt 120 fps. Giá trị dưới 30 fps làm giảm đáng kể trải nghiệm người dùng.

Frame Rate khác với tần số quét màn hình như thế nào?

Frame Rate — số khung hình mỗi giây mà ứng dụng kết xuất. Tần số quét (Refresh Rate) — số lần mỗi giây màn hình cập nhật hình ảnh vật lý. Khi Frame Rate thấp hơn Refresh Rate, màn hình lặp lại khung hình cuối cùng.

Làm thế nào để đo Frame Rate trong Android?

Sử dụng GPU Profiling trong Tùy chọn nhà phát triển, Android Studio Profiler hoặc Firebase Performance. Để đo lập trình — Choreographer.FrameCallback với tính toán khoảng thời gian giữa các khung hình.

Overdraw là gì và nó ảnh hưởng đến Frame Rate như thế nào?

Overdraw — vẽ cùng một pixel nhiều lần trong một khung hình. Mỗi lớp thừa làm tăng thời gian giai đoạn Vẽ và giảm Frame Rate. Overdraw tối ưu là 2x, nghiêm trọng là 4x trở lên.

Dynamic Frame Rate tiết kiệm pin như thế nào?

Trên nội dung tĩnh, Dynamic Frame Rate giảm tần số xuống 30–60 Hz, giảm tải GPU 30–40%. Khi cuộn, tần số tăng lên 90–120 Hz để mượt mà.

Tổng kết

  • Frame Rate — số khung hình mỗi giây quyết định độ mượt của giao diện và hoạt ảnh.
  • Frame Rate mục tiêu — 60 fps (16,6 ms mỗi khung) cho màn hình tiêu chuẩn, 120 fps (8,3 ms) cho tần số quét cao.
  • Các khung hình bị bỏ lỡ gây ra Jank — hiện tượng giật hình nhìn thấy được làm giảm trải nghiệm người dùng.
  • Nguyên nhân chính của Frame Rate thấp — lồng ghép View quá mức, overdraw và kết xuất ngoài màn hình.
  • Choreographer (Android) và CADisplayLink (iOS) đồng bộ hóa kết xuất với VSync.
  • Frame Rate thích ứng cân bằng độ mượt và mức tiêu thụ điện năng, giảm tải GPU đến 40%.
  • Hồ sơ Frame Rate là bước đầu tiên để tối ưu hóa hiệu suất ứng dụng di động.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm