Frame Rate in mobiele apps — wat is het, fps en hoe te verbeteren

Auteur: IT Sectr Gepubliceerd: 2026-03-31 Leestijd: 10 min

Frame Rate — is het aantal frames dat het grafische systeem in één seconde weergeeft. In mobiele apps bepaalt de framesnelheid direct de vloeiendheid van animaties, scrollen en overgangen tussen schermen. Volgens gegevens van Android Developers, 2025 is de beoogde Frame Rate 60 fps voor standaard displays en 120 fps voor apparaten met een hoge verversingssnelheid. Afwijking van de streefwaarde leidt tot visuele haperingen en een verslechterde gebruikerservaring.

Belangrijkste punten

  • Frame Rate — het aantal frames per seconde (fps) dat de vloeiendheid van de UI bepaalt.
  • Standaard beoogde Frame Rate — 60 fps, komt overeen met 16.6 ms per frame.
  • Apparaten met 120 Hz displays vereisen 120 fps (8.3 ms per frame).
  • Overgeslagen frames veroorzaken Jank — merkbare haperingen in animaties.
  • Frame Rate profileren — de eerste stap naar optimalisatie van UI-prestaties.

Wat is Frame Rate

Frame Rate (framesnelheid) — is een metriek gemeten in frames per seconde (fps) die aangeeft hoe vaak per seconde een app het beeld op het scherm ververst. Het menselijk oog neemt beweging als vloeiend waar vanaf 24 fps (film), maar voor interactieve UI is minimaal 60 fps nodig zodat aanrakingen en animaties direct aanvoelen. Elk frame is een volledige cyclus: verwerking van gebruikersinvoer, berekening van de Layout, rendering van de View-hiërarchie en weergave op het scherm. Als een van de fasen het toegewezen tijdbudget overschrijdt (16.6 ms bij 60 fps), wordt het frame overgeslagen en ziet de gebruiker een hapering.

Het is belangrijk om de Frame Rate van de app te onderscheiden van de verversingssnelheid van het display (Refresh Rate). De verversingssnelheid is een kenmerk van het scherm: hoe vaak per seconde het display het beeld fysiek ververst (60, 90, 120 of 144 Hz). Frame Rate — is hoeveel frames per seconde de app kan renderen. Als een app 60 fps produceert op een 120 Hz display, wordt elk tweede frame gedupliceerd — het beeld blijft vloeiend, maar niet zo responsief als het zou kunnen zijn. Volgens Google I/O 2023 kunnen moderne vlaggenschepen 120 fps behouden in eenvoudige UI-scenario’s, maar bij zware belasting (games, complexe lijsten) daalt de snelheid naar 40–60 fps.

Hoe werkt framerendering

Het renderen van een frame in een mobiele app doorloopt een pijplijn van verschillende fasen. In Android omvat de pijplijn: verwerking van invoer (Input), animatie (Animation), meting en plaatsing (Layout), tekenen (Draw), synchronisatie met GPU en weergave op het scherm (Swap). Elke fase wordt uitgevoerd op de CPU of GPU, en de totale tijd van alle fasen mag het framebudget niet overschrijden. Voor 60 fps is het budget 16.6 ms, voor 120 fps — 8.3 ms. Choreographer (Android) en CADisplayLink (iOS) synchroniseren de rendering met de verticale verversing van het display (VSync), zodat een frame alleen wordt weergegeven op het moment van schermverversing, waardoor tearing (scheuren van het beeld) wordt voorkomen.

In iOS is de pijplijn vergelijkbaar: Run Loop verwerkt gebeurtenissen, Core Animation berekent lagen, Render Server (een apart proces) rendert en stuurt het frame naar de GPU. Het verschil in iOS — het aparte Render Server-proces dat de rendering isoleert van de hoofdapp. Als de app de main thread blokkeert, kan Render Server nog steeds het laatste bekende frame weergeven, maar animaties stoppen. Als Render Server zelf niet op tijd is — staat de GPU stil en daalt de Frame Rate. Volgens Apple WWDC 2022 zijn de meest voorkomende oorzaken van lage Frame Rate in iOS overmatige nesting van CALayer, zware shadowPath en offscreen rendering.

Frames volgen via Choreographer

Code in Kotlin abonneert zich op Choreographer.FrameCallback en logt de werkelijke tijd tussen frames. Als het interval groter is dan 16.6 ms — wordt een overgeslagen frame geregistreerd.

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

Verversingssnelheid van het display en Frame Rate

Refresh Rate (verversingssnelheid) — is een hardwarekenmerk van het display dat bepaalt hoe vaak per seconde het scherm het beeld fysiek hertekent. Standaard displays hebben 60 Hz, moderne vlaggenschepen — 90, 120 of 144 Hz. De Frame Rate van de app kan lager, gelijk of hoger zijn dan de verversingssnelheid (in het laatste geval worden overtollige frames weggegooid). Het ideale scenario — Frame Rate komt overeen met Refresh Rate: elke hardwarecyclus krijgt een nieuw frame van de app en beweging is maximaal vloeiend. Als Frame Rate lager is, herhaalt het display het laatste frame, wat wordt waargenomen als micro-haperingen (stutter).

Android en iOS ondersteunen het dynamisch schakelen van de verversingssnelheid. Android 12+ gebruikt Smart Refresh Rate: bij scrollen verhoogt het systeem de snelheid naar 120 Hz, bij statische inhoud verlaagt het naar 60 Hz om batterij te sparen. iOS ProMotion (iPhone 13 Pro en nieuwer) werkt vergelijkbaar — de snelheid varieert van 10 tot 120 Hz afhankelijk van de inhoud. De ontwikkelaar moet controleren of het apparaat hoge verversing ondersteunt en het tijdbudget per frame aanpassen. Als de app geen frame kan renderen in 8.3 ms (voor 120 Hz), is het beter om gedwongen op 60 Hz te werken — dit zorgt voor een stabiele Frame Rate zonder overgeslagen frames.

Type displayRefresh RateBudget per frameApparaten
Standaard60 Hz16.6 msMeeste Android/iOS
Hoog90 Hz11.1 msOnePlus, Pixel 6+
Flagship120 Hz8.3 msiPhone Pro, Galaxy S22+
Gaming144 Hz6.9 msROG Phone, Nubia RedMagic

Meetinstrumenten voor Frame Rate

Voor het meten van Frame Rate in mobiele apps zijn zowel ingebouwde tools van de platforms als externe profilers beschikbaar. In Android is de belangrijkste tool GPU Profiling (Developer Options → Profile GPU Rendering) die de tijdschaal van elk frame toont met uitsplitsing per fase (Draw, Prepare, Process, Execute). Een gedetailleerdere analyse biedt Android Studio Profiler — hij registreert een volledig renderprofiel met vermelding van specifieke Views die hertekenen veroorzaken. In iOS wordt Instruments met de Core Animation-sjabloon gebruikt — het toont FPS, rendertijd van lagen en het aantal offscreen-renders.

Voor productiemonitoring van Frame Rate wordt Firebase Performance (Android) gebruikt — het verzamelt Frame Rate op de achtergrond en aggregeert per apparaat, OS-versie en sessie. In iOS biedt MetricKit vergelijkbare gegevens via MXAnimatoryMetric. Voor games en Flutter-apps worden FrameTimingCallback (Flutter) en Unity Profiler gebruikt. Het is belangrijk om niet de gemiddelde Frame Rate te meten, maar percentielen: P50, P90 en P99. Een app kan een gemiddelde van 55 fps tonen, maar P99 = 30 fps hebben — dit betekent dat 1% van de tijd gebruikers sterke haperingen zien en dit is voldoende voor negatieve recensies.

Frame Rate meten in Flutter

Een voorbeeld in Dart laat zien hoe je je abonneert op FrameTimingCallback in Flutter en het aantal overgeslagen frames logt. De callback wordt geactiveerd na elk voltooid frame.

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

Optimalisatie van de framesnelheid

Optimalisatie van Frame Rate begint met het identificeren van knelpunten in de renderpijplijn. In de Layout-fase zijn de belangrijkste problemen overmatige nesting van de View-hiërarchie, gebruik van relatieve Layouts (RelativeLayout met veel regels) en frequente aanroepen van requestLayout. Oplossing — gebruik van ConstraintLayout of een platte hiërarchie, vermijd nesting van meer dan 5–6 niveaus. In de Draw-fase — overtekenen (overdraw): wanneer een pixel meerdere keren per frame wordt getekend. Bijvoorbeeld een witte achtergrond van Activity onder een semi-transparante fragment, waaronder nog een laag — elke pixel wordt drie keer getekend. De tool Debug GPU Overdraw toont probleemzones met kleurindicatie. Het wordt aanbevolen om overdraw op 2x of lager te houden.

In iOS zijn de belangrijkste problemen zware cornerRadius en masksToBounds — ze veroorzaken offscreen rendering, waarbij Core Animation een tijdelijke buffer maakt, erin tekent en vervolgens het resultaat naar het scherm kopieert. Offscreen rendering is gemakkelijk te zien in Instruments Core Animation: als de Renderer-regel rood is — zijn er problemen. Oplossing — gebruik UIImageView met vooraf bijgesneden afbeeldingen in plaats van cornerRadius, vermijd groupOpacity en shouldRasterize zonder noodzaak. Voor beide platforms is het cruciaal om het aantal aanroepen van invalidate() en setNeedsDisplay() te minimaliseren — elke dergelijke aanroep start een volledige hertekeningscyclus van de weergave.

Hiërarchie optimaliseren in Android

Code demonstreert het vervangen van diepe nesting van RelativeLayout door een platte structuur met ConstraintLayout. Het verminderen van het nestniveau van 4 naar 1 verkort de Layout-tijd met 30–50%.

kotlin
// Voorbeeld: platte structuur via 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
        // gegevens koppelen zonder de hele container te hertekenen
    }
}

Adaptieve snelheden en Dynamic Frame Rate

Moderne mobiele apps gebruiken steeds vaker adaptieve Frame Rate — een systeem dat de beoogde snelheid dynamisch aanpast aan het huidige scenario. Bij snel scrollen heeft de lijst 120 fps nodig voor vloeiendheid, bij een statisch scherm is 60 fps of zelfs 30 fps voor video voldoende. In Android wordt aanpassing gerealiseerd via Choreographer.setFrameInterval (API 33+) en Window.setFrameRate. De ontwikkelaar kan het systeem een voorkeurssnelheid aangeven: setPreferredRefreshRate in SurfaceView of setFrameRate in Window. iOS beheert automatisch de snelheid via ProMotion, maar de ontwikkelaar kan expliciet preferredFramesPerSecond instellen voor CADisplayLink.

Dynamische Frame Rate is vooral belangrijk voor games en apps met animaties. Volgens Google bespaart het verlagen van Frame Rate van 120 naar 60 Hz op een statisch scherm tot 30–40% GPU-energie. Om de beste balans tussen vloeiendheid en energieverbruik te bereiken, wordt aanbevolen: meet de werkelijke Frame Rate in verschillende scenarioën, stel de beoogde fps in op basis van de scène (game — 60, menu — 30, video — 24) en schakel modi via Lifecycle-aware componenten, zodat de app bij minimalisatie geen resources verspilt aan het renderen van 120 fps op de achtergrond.

Voorkeurs Frame Rate instellen

Code in Swift stelt preferredFramesPerSecond in voor CADisplayLink in iOS. Bij scrollen stijgt de snelheid naar 120 Hz, bij stoppen — daalt naar 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() {
        // animatie-update
    }
}

Veelgestelde vragen

Welke Frame Rate wordt als goed beschouwd voor een mobiele app?

Voor mobiele apps is de beoogde Frame Rate 60 fps (16.6 ms per frame). Voor apparaten met 120 Hz displays is 120 fps wenselijk. Waarden onder 30 fps verslechteren de gebruikerservaring aanzienlijk.

Wat is het verschil tussen Frame Rate en de verversingssnelheid van het display?

Frame Rate — hoeveel frames per seconde de app rendert. Refresh Rate — hoe vaak per seconde het display het beeld fysiek ververst. Wanneer Frame Rate lager is dan Refresh Rate, herhaalt het display het laatste frame.

Hoe meet je Frame Rate in Android?

Gebruik GPU Profiling in Developer Options, Android Studio Profiler of Firebase Performance. Voor programmatische meting — Choreographer.FrameCallback met berekening van het interval tussen frames.

Wat is overdraw en hoe beïnvloedt het Frame Rate?

Overdraw — het meerdere keren per frame tekenen van dezelfde pixel. Elke extra laag verhoogt de tijd van de Draw-fase en verlaagt de Frame Rate. Optimale overdraw is 2x, kritisch — 4x en hoger.

Hoe bespaart Dynamic Frame Rate batterij?

Bij statische inhoud verlaagt Dynamic Frame Rate de snelheid naar 30–60 Hz, waardoor de GPU-belasting met 30–40% afneemt. Bij scrollen stijgt de snelheid naar 90–120 Hz voor vloeiendheid.

Samenvatting

  • Frame Rate — het aantal frames per seconde dat de vloeiendheid van UI en animaties bepaalt.
  • Beoogde Frame Rate — 60 fps (16.6 ms) voor standaard displays, 120 fps (8.3 ms) voor hoge verversingssnelheid.
  • Overgeslagen frames veroorzaken Jank — zichtbare haperingen die de gebruikerservaring verslechteren.
  • Belangrijkste oorzaken van lage Frame Rate — overmatige View-nesting, overdraw en offscreen rendering.
  • Choreographer (Android) en CADisplayLink (iOS) synchroniseren rendering met VSync.
  • Adaptieve Frame Rate balanceert vloeiendheid en energieverbruik, waardoor de GPU-belasting tot 40% afneemt.
  • Frame Rate profileren — de eerste stap naar optimalisatie van mobiele app-prestaties.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook