Frame Rate i mobilappar — vad är det, fps och hur man förbättrar

Författare: IT Sectr Publicerad: 2026-03-31 Lästid: 10 min

Frame Rate — är antalet bildrutor som grafiksystemet visar under en sekund. I mobilappar avgör bildfrekvensen direkt hur jämna animationer, scrollning och övergångar mellan skärmar är. Enligt uppgifter från Android Developers, 2025 är mål-Frame Rate 60 fps för standarddisplayer och 120 fps för enheter med hög uppdateringsfrekvens. Avvikelse från målvärdet leder till visuella hackningar och försämrad användarupplevelse.

Huvudpunkter

  • Frame Rate — antal bildrutor per sekund (fps) som bestämmer UI:s jämnhet.
  • Standard mål-Frame Rate — 60 fps, motsvarar 16.6 ms per bildruta.
  • Enheter med 120 Hz-displayer kräver 120 fps (8.3 ms per bildruta).
  • Missade bildrutor orsakar Jank — märkbara hackningar i animationer.
  • Profilering av Frame Rate — första steget mot optimering av UI-prestanda.

Vad är Frame Rate

Frame Rate (bildfrekvens) — är ett mått mätt i bildrutor per sekund (fps) som visar hur många gånger per sekund appen uppdaterar bilden på skärmen. Det mänskliga ögat uppfattar rörelse som jämn från 24 fps (film), men för interaktivt UI krävs minst 60 fps för att beröringar och animationer ska kännas omedelbara. Varje bildruta är en fullständig cykel: bearbetning av användarinmatning, beräkning av Layout, rendering av View-hierarkin och visning på skärmen. Om någon av faserna överskrider den tilldelade tidsbudgeten (16.6 ms vid 60 fps) hoppas bildrutan över och användaren ser en hackning.

Det är viktigt att skilja appens Frame Rate från skärmens uppdateringsfrekvens (Refresh Rate). Uppdateringsfrekvensen är en skärmegenskap: hur många gånger per sekund displayen fysiskt uppdaterar bilden (60, 90, 120 eller 144 Hz). Frame Rate — är hur många bildrutor per sekund som appen hinner rendera. Om appen producerar 60 fps på en 120 Hz-display kommer varannan bildruta att dupliceras — bilden förblir jämn, men inte lika responsiv som den skulle kunna vara. Enligt Google I/O 2023 kan moderna flaggskepp hålla 120 fps i enkla UI-scenarier, men vid tung belastning (spel, komplexa listor) sjunker frekvensen till 40–60 fps.

Hur fungerar rendering av bildrutor

Rendering av en bildruta i en mobilapp går igenom en pipeline med flera steg. I Android omfattar pipelinen: bearbetning av inmatning (Input), animation (Animation), mätning och placering (Layout), ritning (Draw), synkronisering med GPU och visning på skärmen (Swap). Varje steg utförs på CPU eller GPU, och den totala tiden för alla steg får inte överskrida bildrutans budget. För 60 fps är budgeten 16.6 ms, för 120 fps — 8.3 ms. Choreographer (Android) och CADisplayLink (iOS) synkroniserar renderingen med skärmens vertikala uppdatering (VSync), vilket garanterar att en bildruta endast visas vid skärmuppdateringsögonblicket och förhindrar bildrivning (tearing).

I iOS är pipelinen liknande: Run Loop bearbetar händelser, Core Animation beräknar lager, Render Server (en separat process) renderar och skickar bildrutan till GPU:n. Skillnaden i iOS — den separata Render Server-processen som isolerar renderingen från huvudappen. Om appen blockerar huvudtråden kan Render Server fortfarande visa den senast kända bildrutan, men animationer stannar. Om Render Server själv inte hinner med — är GPU:n overksam och Frame Rate sjunker. Enligt Apple WWDC 2022 är de vanligaste orsakerna till lågt Frame Rate i iOS överdriven nästling av CALayer, tunga shadowPath och rendering utanför skärmen (offscreen rendering).

Spåra bildrutor via Choreographer

Kod i Kotlin prenumererar på Choreographer.FrameCallback och loggar den faktiska tiden mellan bildrutor. Om intervallet överstiger 16.6 ms — registreras en missad bildruta.

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

Skärmens uppdateringsfrekvens och Frame Rate

Refresh Rate (uppdateringsfrekvens) — är en hårdvaruegenskap hos displayen som bestämmer hur många gånger per sekund skärmen fysiskt ritar om bilden. Standarddisplayer har 60 Hz, moderna flaggskepp — 90, 120 eller 144 Hz. Appens Frame Rate kan vara lägre, lika med eller högre än uppdateringsfrekvensen (i det senare fallet kastas överskjutande bildrutor bort). Det ideala scenariot — Frame Rate sammanfaller med Refresh Rate: varje hårdvarucykel får en ny bildruta från appen och rörelsen är maximalt jämn. Om Frame Rate är lägre upprepar displayen den sista bildrutan, vilket uppfattas som mikrohackningar (stutter).

Android och iOS stöder dynamisk växling av uppdateringsfrekvens. Android 12+ använder Smart Refresh Rate: vid scrollning höjer systemet frekvensen till 120 Hz, vid statiskt innehåll sänker den till 60 Hz för att spara batteri. iOS ProMotion (iPhone 13 Pro och nyare) fungerar liknande — frekvensen varierar från 10 till 120 Hz beroende på innehållet. Utvecklaren bör kontrollera om enheten stöder hög frekvens och anpassa tidsbudgeten per bildruta. Om appen inte hinner rendera en bildruta på 8.3 ms (för 120 Hz) är det bättre att tvinga den att arbeta på 60 Hz — detta ger en stabil Frame Rate utan missade bildrutor.

Typ av displayRefresh RateBudget per bildrutaEnheter
Standard60 Hz16.6 msDe flesta Android/iOS
Hög90 Hz11.1 msOnePlus, Pixel 6+
Flaggskepp120 Hz8.3 msiPhone Pro, Galaxy S22+
Spel144 Hz6.9 msROG Phone, Nubia RedMagic

Mätverktyg för Frame Rate

För att mäta Frame Rate i mobilappar finns både plattformarnas inbyggda verktyg och externa profilerare tillgängliga. I Android är huvudverktyget GPU Profiling (Developer Options → Profile GPU Rendering) som visar tidsskalan för varje bildruta uppdelad per fas (Draw, Prepare, Process, Execute). Mer detaljerad analys tillhandahålls av Android Studio Profiler — den registrerar en fullständig renderingsprofil med angivelse av specifika View som orsakar omritning. I iOS används Instruments med mallen Core Animation — den visar FPS, renderingstid för lager och antal renderingar utanför skärmen.

För övervakning av Frame Rate i produktion används Firebase Performance (Android) — den samlar in Frame Rate i bakgrunden och aggregerar per enhet, OS-version och session. I iOS tillhandahåller MetricKit liknande data via MXAnimatoryMetric. För spel och Flutter-appar används FrameTimingCallback (Flutter) och Unity Profiler. Det är viktigt att mäta inte genomsnittlig Frame Rate, utan percentiler: P50, P90 och P99. En app kan visa genomsnittligt 55 fps men ha P99 = 30 fps — detta innebär att 1% av tiden ser användare kraftiga hackningar och det räcker för negativa recensioner.

Mäta Frame Rate i Flutter

Exemplet i Dart visar hur man prenumererar på FrameTimingCallback i Flutter och loggar antalet missade bildrutor. Callbacken utlöses efter varje slutförd bildruta.

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

Optimering av bildfrekvens

Optimering av Frame Rate börjar med att identifiera flaskhalsar i renderingspipelinen. I Layout-fasen är de främsta problemen överdriven nästling av View-hierarkin, användning av relativa Layouts (RelativeLayout med många regler) och frekventa anrop till requestLayout. Lösning — använd ConstraintLayout eller en platt hierarki, undvik nästling av mer än 5–6 nivåer. I Draw-fasen — omritning (overdraw): när en pixel ritas flera gånger per bildruta. Till exempel en vit bakgrund för Activity under ett halvgenomskinligt fragment, under vilket det finns ytterligare ett lager — varje pixel ritas tre gånger. Verktyget Debug GPU Overdraw visar problemområden med färgindikering. Det rekommenderas att hålla overdraw på nivån 2x eller lägre.

I iOS är de främsta problemen tunga cornerRadius och masksToBounds — de orsakar rendering utanför skärmen (offscreen rendering), där Core Animation skapar en tillfällig buffer, ritar i den och sedan kopierar resultatet till skärmen. Offscreen rendering är lätt att se i Instruments Core Animation: om raden Renderer är röd — finns problem. Lösning — använd UIImageView med förbeskurna bilder istället för cornerRadius, undvik groupOpacity och shouldRasterize utan absolut nödvändighet. För båda plattformarna är det kritiskt att minimera antalet anrop till invalidate() och setNeedsDisplay() — varje sådant anrop startar en fullständig omritningscykel för vyn.

Optimera hierarkin i Android

Koden demonstrerar ersättning av djup nästling av RelativeLayout med en platt struktur med ConstraintLayout. Att minska nästlingsnivån från 4 till 1 förkortar Layout-tiden med 30–50%.

kotlin
// Exempel: platt struktur 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
        // binda data utan att rita om hela containern
    }
}

Adaptiva frekvenser och Dynamic Frame Rate

Moderna mobilappar använder allt oftare adaptiv Frame Rate — ett system som dynamiskt anpassar målfrekvensen till det aktuella scenariot. Vid snabb scrollning kräver listan 120 fps för jämnhet, vid en statisk skärm räcker 60 fps eller till och med 30 fps för video. I Android implementeras anpassning via Choreographer.setFrameInterval (API 33+) och Window.setFrameRate. Utvecklaren kan ange önskad frekvens till systemet: setPreferredRefreshRate i SurfaceView eller setFrameRate i Window. iOS hanterar automatiskt frekvensen via ProMotion, men utvecklaren kan explicit ställa in preferredFramesPerSecond för CADisplayLink.

Dynamisk Frame Rate är särskilt viktig för spel och appar med animationer. Enligt Google sparar en sänkning av Frame Rate från 120 till 60 Hz på en statisk skärm upp till 30–40% GPU-energi. För att uppnå bästa balans mellan jämnhet och energiförbrukning rekommenderas: mät den faktiska Frame Rate i olika scenarier, ställ in mål-fps beroende på scen (spel — 60, meny — 30, video — 24) och växla lägen via Lifecycle-aware-komponenter, så att appen vid minimering inte slösar resurser på att rendera 120 fps i bakgrunden.

Ställa in önskad Frame Rate

Kod i Swift ställer in preferredFramesPerSecond för CADisplayLink i iOS. Vid scrollning stiger frekvensen till 120 Hz, vid stopp — sjunker till 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() {
        // animationsuppdatering
    }
}

Vanliga frågor

Vilken Frame Rate anses bra för en mobilapp?

För mobilappar är mål-Frame Rate 60 fps (16.6 ms per bildruta). För enheter med 120 Hz-display är 120 fps önskvärt. Värden under 30 fps försämrar användarupplevelsen märkbart.

Vad är skillnaden mellan Frame Rate och skärmens uppdateringsfrekvens?

Frame Rate — hur många bildrutor per sekund appen renderar. Refresh Rate — hur många gånger per sekund displayen fysiskt uppdaterar bilden. När Frame Rate är lägre än Refresh Rate upprepar displayen den sista bildrutan.

Hur mäter man Frame Rate i Android?

Använd GPU Profiling i Developer Options, Android Studio Profiler eller Firebase Performance. För programmeringsmässig mätning — Choreographer.FrameCallback med beräkning av intervallet mellan bildrutor.

Vad är overdraw och hur påverkar det Frame Rate?

Overdraw — ritning av samma pixel flera gånger per bildruta. Varje extra lager ökar tiden för Draw-fasen och sänker Frame Rate. Optimal overdraw är 2x, kritisk — 4x och högre.

Hur sparar Dynamic Frame Rate batteri?

Vid statiskt innehåll sänker Dynamic Frame Rate frekvensen till 30–60 Hz, vilket minskar GPU-belastningen med 30–40%. Vid scrollning stiger frekvensen till 90–120 Hz för jämnhet.

Sammanfattning

  • Frame Rate — antal bildrutor per sekund som bestämmer jämnheten hos UI och animationer.
  • Mål-Frame Rate — 60 fps (16.6 ms) för standarddisplayer, 120 fps (8.3 ms) för hög uppdateringsfrekvens.
  • Missade bildrutor orsakar Jank — synliga hackningar som försämrar användarupplevelsen.
  • Främsta orsaker till lågt Frame Rate — överdriven View-nästling, overdraw och rendering utanför skärmen.
  • Choreographer (Android) och CADisplayLink (iOS) synkroniserar rendering med VSync.
  • Adaptiv Frame Rate balanserar jämnhet och energiförbrukning, minskar GPU-belastningen med upp till 40%.
  • Profilering av Frame Rate — första steget mot optimering av mobilappsprestanda.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också