Frame Rate у мобільних застосунках — що це, fps та як підвищити

Автор: IT Sectr Опубліковано: 2026-03-31 Час читання: 10 хв

Frame Rate — це кількість кадрів, яку графічна система відображає за одну секунду. У мобільних застосунках частота кадрів безпосередньо визначає плавність анімацій, скролінгу та переходів між екранами. За даними Android Developers, 2025, цільовий Frame Rate становить 60 fps для стандартних дисплеїв та 120 fps для пристроїв із високою частотою оновлення. Відхилення від цільового значення призводить до візуальних заїкань та погіршення користувацького досвіду.

Головне

  • Frame Rate — кількість кадрів на секунду (fps), що визначає плавність інтерфейсу.
  • Стандартний цільовий Frame Rate — 60 fps, що відповідає 16.6 мс на кадр.
  • Пристрої з дисплеями 120 Гц потребують 120 fps (8.3 мс на кадр).
  • Пропущені кадри викликають Jank — помітні заїкання анімації.
  • Профілювання Frame Rate — перший крок до оптимізації продуктивності інтерфейсу.

Що таке Frame Rate

Frame Rate (частота кадрів) — це метрика, що вимірюється в кадрах на секунду (fps) та показує, скільки разів за секунду застосунок оновлює зображення на екрані. Людське око сприймає рух як плавний від 24 fps (кіно), але для інтерактивного інтерфейсу потрібно мінімум 60 fps, щоб дотики та анімації відчувалися миттєвими. Кожен кадр — це повний цикл: обробка користувацького введення, обчислення Layout, рендеринг ієрархії View та виведення на екран. Якщо будь-який із цих етапів перевищує виділений бюджет часу (16.6 мс при 60 fps), кадр пропускається, і користувач бачить заїкання.

Важливо розрізняти Frame Rate застосунку та частоту оновлення дисплея (Refresh Rate). Частота оновлення — це характеристика екрана: скільки разів на секунду дисплей фізично оновлює зображення (60, 90, 120 або 144 Гц). Frame Rate — це скільки кадрів за секунду встигає відрендерити застосунок. Якщо застосунок видає 60 fps при дисплеї 120 Гц, кожен другий кадр дублюватиметься — зображення залишиться плавним, але не таким чуйним, як могло б бути. За даними Google I/O 2023, сучасні флагмани здатні підтримувати 120 fps у простих сценаріях інтерфейсу, але під важким навантаженням (ігри, складні списки) частота падає до 40–60 fps.

Як працює рендеринг кадрів

Рендеринг кадру в мобільному застосунку проходить через конвеєр із кількох етапів. В Android конвеєр включає: обробка введення (Input), анімація (Animation), вимірювання та розташування (Layout), малювання (Draw), синхронізація з GPU та виведення на екран (Swap). Кожен етап виконується на CPU або GPU, і сумарний час усіх етапів не має перевищувати бюджет кадру. Для 60 fps бюджет — 16.6 мс, для 120 fps — 8.3 мс. Choreographer (Android) та CADisplayLink (iOS) синхронізують рендеринг із вертикальною розгорткою дисплея (VSync), гарантуючи, що кадр виводиться лише в момент оновлення екрана, уникаючи tearing.

В iOS конвеєр схожий: Run Loop обробляє події, Core Animation обчислює шари, Render Server (окремий процес) рендерить та відправляє кадр на GPU. Відмінність iOS — виділений процес Render Server, який ізолює рендеринг від основного застосунку. Якщо застосунок блокує головний потік, Render Server все одно може відмалювати останній відомий кадр, але анімації зупиняться. Якщо Render Server сам не встигає — GPU простоює, і Frame Rate падає. За даними Apple WWDC 2022, найпоширеніші причини низького Frame Rate в iOS — надмірна вкладеність CALayer, важкі shadowPath та offscreen rendering.

Відстеження кадрів через Choreographer

Код на Kotlin підписується на Choreographer.FrameCallback та логує фактичний час між кадрами. Якщо інтервал перевищує 16.6 мс — фіксується пропущений кадр.

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

Частота оновлення дисплея та Frame Rate

Refresh Rate (частота оновлення) — апаратна характеристика дисплея, що визначає, скільки разів на секунду екран фізично перемальовує зображення. Стандартні дисплеї мають 60 Гц, сучасні флагмани — 90, 120 або 144 Гц. Frame Rate застосунку може бути нижчим, дорівнювати або перевищувати частоту оновлення (в останньому випадку зайві кадри відкидаються). Ідеальний сценарій — Frame Rate збігається з Refresh Rate: кожен апаратний цикл отримує новий кадр від застосунку, і рух максимально плавний. Якщо Frame Rate нижчий, дисплей повторює останній кадр, що сприймається як мікро-заїкання.

Android та iOS підтримують динамічне перемикання частоти оновлення. Android 12+ використовує Smart Refresh Rate: під час прокручування система піднімає частоту до 120 Гц, на статичному контенті знижує до 60 Гц для економії батареї. iOS ProMotion (iPhone 13 Pro та новіші) працює аналогічно — частота варіюється від 10 до 120 Гц залежно від контенту. Розробник має перевіряти, чи підтримує пристрій високу частоту, та адаптувати бюджет часу на кадр. Якщо застосунок не встигає відрендерити кадр за 8.3 мс (для 120 Гц), краще примусово працювати на 60 Гц — це забезпечить стабільний Frame Rate без пропущених кадрів.

Тип дисплеяRefresh RateБюджет на кадрПристрої
Стандартний60 Гц16.6 мсБільшість Android/iOS
Високий90 Гц11.1 мсOnePlus, Pixel 6+
Флагманський120 Гц8.3 мсiPhone Pro, Galaxy S22+
Ігровий144 Гц6.9 мсROG Phone, Nubia RedMagic

Інструменти вимірювання Frame Rate

Для вимірювання Frame Rate в мобільних застосунках доступні як вбудовані інструменти платформ, так і сторонні профілювальники. В Android основний інструмент — GPU Profiling (Developer Options → Profile GPU Rendering), який показує часову шкалу кожного кадру з розбивкою за етапами (Draw, Prepare, Process, Execute). Більш детальний аналіз надає Android Studio Profiler — він записує повний профіль рендерингу із зазначенням конкретних View, що викликають перемальовування. В iOS використовується Instruments із шаблоном Core Animation — він показує FPS, час рендерингу шарів та кількість offscreen-рендерів.

Для продакшн-моніторингу Frame Rate застосовується Firebase Performance (Android) — він збирає Frame Rate у фоні та агрегує за пристроями, версіями ОС та сесіями. В iOS MetricKit надає аналогічні дані через MXAnimatoryMetric. Для ігор та Flutter-застосунків використовуються FrameTimingCallback (Flutter) та Unity Profiler. Важливо вимірювати не середній Frame Rate, а перцентилі: P50, P90 та P99. Застосунок може показувати середні 55 fps, але мати P99 = 30 fps — це означає, що 1% часу користувачі бачать сильні заїкання, і цього достатньо для негативних відгуків.

Вимірювання Frame Rate у Flutter

Приклад на Dart показує, як підписатися на FrameTimingCallback у Flutter та логувати кількість пропущених кадрів. Callback спрацьовує після кожного завершеного кадру.

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

Оптимізація частоти кадрів

Оптимізація Frame Rate починається з виявлення вузьких місць у конвеєрі рендерингу. На етапі Layout основні проблеми — надмірна вкладеність ієрархії View, використання відносних Layout (RelativeLayout із великою кількістю правил) та часті виклики requestLayout. Рішення — використовувати ConstraintLayout або Flat-ієрархію, уникати вкладеності більше 5–6 рівнів. На етапі Draw — перемальовування (overdraw): коли піксель малюється кілька разів за кадр. Наприклад, білий фон Activity під напівпрозорим фрагментом, під яким ще один шар — кожен піксель малюється тричі. Інструмент Debug GPU Overdraw показує проблемні зони кольоровою індикацією. Рекомендується утримувати overdraw на рівні 2x та нижче.

В iOS основні проблеми: важкі cornerRadius та masksToBounds — вони викликають offscreen rendering, при якому Core Animation створює тимчасовий буфер, малює в нього, потім копіює результат на екран. Offscreen rendering легко помітити в Instruments Core Animation: якщо рядок Renderer червоний — є проблеми. Рішення — використовувати UIImageView із заздалегідь обрізаними зображеннями замість cornerRadius, уникати groupOpacity та shouldRasterize без крайньої потреби. Для обох платформ критично мінімізувати кількість викликів invalidate() та setNeedsDisplay() — кожен такий виклик запускає повний цикл перемальовування в'ю.

Оптимізація ієрархії в Android

Код демонструє заміну глибокої вкладеності RelativeLayout на плоску структуру ConstraintLayout. Зменшення рівня вкладеності з 4 до 1 скорочує час Layout на 30–50%.

kotlin
// Приклад: плоска структура через 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
        // прив'язуємо дані без перемальовування всього контейнера
    }
}

Адаптивні частоти та Dynamic Frame Rate

Сучасні мобільні застосунки все частіше використовують адаптивний Frame Rate — систему, яка динамічно підлаштовує цільову частоту під поточний сценарій. При швидкому прокручуванні список потребує 120 fps для плавності, при статичному екрані достатньо 60 fps або навіть 30 fps для відео. В Android адаптація реалізується через Choreographer.setFrameInterval (API 33+) та Window.setFrameRate. Розробник може вказати системі бажану частоту: setPreferredRefreshRate у SurfaceView або setFrameRate у Window. iOS автоматично керує частотою через ProMotion, але розробник може явно задавати preferredFramesPerSecond для CADisplayLink.

Динамічний Frame Rate особливо важливий для ігор та застосунків з анімаціями. За даними Google, зниження Frame Rate з 120 до 60 Гц на статичному екрані економить до 30–40% енергії GPU. Для досягнення найкращого балансу між плавністю та енергоспоживанням рекомендується: вимірювати фактичний Frame Rate у різних сценаріях, встановлювати цільовий fps залежно від сцени (гра — 60, меню — 30, відео — 24) та перемикати режими через Lifecycle-aware компоненти, щоб при згортанні застосунок не витрачав ресурси на рендеринг 120 fps у фоні.

Встановлення бажаного Frame Rate

Код на Swift задає preferredFramesPerSecond для CADisplayLink в iOS. При прокручуванні частота підвищується до 120 Гц, при зупинці — знижується до 60 Гц.

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() {
        // оновлення анімації
    }
}

Часті запитання

Який Frame Rate вважається хорошим для мобільного застосунку?

Для мобільних застосунків цільовий Frame Rate — 60 fps (16.6 мс на кадр). Для пристроїв із дисплеями 120 Гц бажано 120 fps. Значення нижче 30 fps помітно погіршують користувацький досвід.

Чим Frame Rate відрізняється від частоти оновлення дисплея?

Frame Rate — скільки кадрів на секунду рендерить застосунок. Refresh Rate — скільки разів на секунду дисплей фізично оновлює зображення. При Frame Rate нижче Refresh Rate дисплей дублює останній кадр.

Як виміряти Frame Rate в Android?

Використовуйте GPU Profiling у Developer Options, Android Studio Profiler або Firebase Performance. Для програмного вимірювання — Choreographer.FrameCallback з обчисленням інтервалу між кадрами.

Що таке overdraw і як він впливає на Frame Rate?

Overdraw — перемальовування одного пікселя кілька разів за кадр. Кожен зайвий шар збільшує час Draw-фази та знижує Frame Rate. Оптимальний overdraw — 2x, критичний — 4x і вище.

Як динамічний Frame Rate економить батарею?

При статичному контенті Dynamic Frame Rate знижує частоту до 30–60 Гц, зменшуючи навантаження на GPU на 30–40%. При прокручуванні частота підвищується до 90–120 Гц для плавності.

Підсумки

  • Frame Rate — кількість кадрів на секунду, що визначає плавність UI та анімацій.
  • Цільовий Frame Rate — 60 fps (16.6 мс на кадр) для стандартних дисплеїв, 120 fps (8.3 мс) для High Refresh Rate.
  • Пропущені кадри викликають Jank — видимі заїкання, що погіршують користувацький досвід.
  • Основні причини низького Frame Rate — надмірна вкладеність View, overdraw та offscreen rendering.
  • Choreographer (Android) та CADisplayLink (iOS) синхронізують рендеринг із VSync.
  • Адаптивний Frame Rate балансує між плавністю та енергоспоживанням, знижуючи навантаження на GPU до 40%.
  • Профілювання Frame Rate — перший крок до оптимізації продуктивності мобільного застосунку.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також