Frame Rate в мобилните приложения — какво е, fps и как да я подобрим

Автор: IT Sectr Публикувано: 2026-03-31 Време за четене: 10 мин

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

Основни точки

  • Frame Rate — брой кадри в секунда (fps), определящ плавността на UI.
  • Стандартен целеви Frame Rate — 60 fps, съответства на 16.6 ms на кадър.
  • Устройства с 120 Hz дисплеи изискват 120 fps (8.3 ms на кадър).
  • Пропуснатите кадри причиняват Jank — забележими заеквания на анимацията.
  • Профилирането на Frame Rate — първа стъпка към оптимизиране производителността на UI.

Какво е Frame Rate

Frame Rate (честота на кадрите) — е метрика, измервана в кадри в секунда (fps), която показва колко пъти в секунда приложението обновява изображението на екрана. Човешкото око възприема движението като плавно от 24 fps (кино), но за интерактивен UI са необходими минимум 60 fps, за да се усещат докосванията и анимациите моментални. Всеки кадър е пълен цикъл: обработка на потребителския вход, изчисляване на Layout, рендеринг на View йерархията и извеждане на екрана. Ако някой от етапите надхвърли определения времеви бюджет (16.6 ms при 60 fps), кадърът се пропуска и потребителят вижда заекване.

Важно е да различаваме Frame Rate на приложението от честотата на опресняване на дисплея (Refresh Rate). Честотата на опресняване е характеристика на екрана: колко пъти в секунда дисплеят физически опреснява изображението (60, 90, 120 или 144 Hz). Frame Rate — е колко кадъра в секунда приложението успява да рендерира. Ако приложението произвежда 60 fps на 120 Hz дисплей, всеки втори кадър ще бъде дублиран — изображението остава плавно, но не толкова отзивчиво, колкото би могло да бъде. Според Google I/O 2023, съвременните флагмани могат да поддържат 120 fps в прости UI сценарии, но при тежки натоварвания (игри, сложни списъци) честотата пада до 40–60 fps.

Как работи рендерингът на кадри

Рендерингът на кадър в мобилно приложение преминава през тръбопровод от няколко етапа. В Android тръбопроводът включва: обработка на вход (Input), анимация (Animation), измерване и разположение (Layout), рисуване (Draw), синхронизация с GPU и извеждане на екрана (Swap). Всеки етап се изпълнява на CPU или GPU, а общото време на всички етапи не трябва да надвишава бюджета на кадъра. За 60 fps бюджетът е 16.6 ms, за 120 fps — 8.3 ms. 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 ms — се записва пропуснат кадър.

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 Hz, съвременните флагмани — 90, 120 или 144 Hz. Frame Rate на приложението може да бъде по-нисък, равен или по-висок от честотата на опресняване (в последния случай излишните кадри се изхвърлят). Идеалният сценарий — Frame Rate съвпада с Refresh Rate: всеки хардуерен цикъл получава нов кадър от приложението и движението е максимално плавно. Ако Frame Rate е по-нисък, дисплеят повтаря последния кадър, което се възприема като микро-заеквания (stutter).

Android и iOS поддържат динамично превключване на честотата на опресняване. Android 12+ използва Smart Refresh Rate: при скролване системата повишава честотата до 120 Hz, при статично съдържание я намалява до 60 Hz за пестене на батерия. iOS ProMotion (iPhone 13 Pro и по-нови) работи аналогично — честотата варира от 10 до 120 Hz в зависимост от съдържанието. Разработчикът трябва да провери дали устройството поддържа висока честота и да адаптира времевия бюджет на кадър. Ако приложението не може да рендерира кадър за 8.3 ms (за 120 Hz), по-добре е принудително да работи на 60 Hz — това ще осигури стабилен Frame Rate без пропуснати кадри.

Тип дисплейRefresh RateБюджет на кадърУстройства
Стандартен60 Hz16.6 msПовечето Android/iOS
Висок90 Hz11.1 msOnePlus, Pixel 6+
Флагмански120 Hz8.3 msiPhone Pro, Galaxy S22+
Игрови144 Hz6.9 msROG 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, време за рендеринг на слоеве и брой рендеринги извън екрана.

За мониторинг на 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 или плоска йерархия, избягване на влагане повече от 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 Hz на статичен екран спестява до 30–40% енергия на GPU. За постигане на най-добрия баланс между плавност и консумация на енергия се препоръчва: измерване на действителния Frame Rate в различни сценарии, задаване на целеви fps в зависимост от сцената (игра — 60, меню — 30, видео — 24) и превключване на режими чрез Lifecycle-aware компоненти, така че приложението при минимизиране да не харчи ресурси за рендериране на 120 fps на заден план.

Задаване на предпочитан Frame Rate

Код на Swift задава preferredFramesPerSecond за CADisplayLink в iOS. При скролване честотата се повишава до 120 Hz, при спиране — спада до 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() {
        // актуализация на анимация
    }
}

Често задавани въпроси

Какъв Frame Rate се счита за добър за мобилно приложение?

За мобилни приложения целевият Frame Rate е 60 fps (16.6 ms на кадър). За устройства с дисплеи 120 Hz е желателен 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 Hz, намалявайки натоварването на GPU с 30–40%. При скролване честотата се повишава до 90–120 Hz за плавност.

Обобщение

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

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също