Jank för mobilappar — vad det är, orsaker och åtgärd

Författare: IT Sectr Publicerad: 2026-04-01 Lästid: 10 min

Jank — är en term som betecknar märkbara hackningar eller “stamning” i gränssnittsanimationer, orsakade av att enskilda bildrutor hoppas över. I mobilappar uppstår Jank när renderingstiden för en bildruta överskrider budgeten som tilldelats av displayens uppdateringsfrekvens. Enligt Android Developers, 2025 är Jank den främsta orsaken till den subjektiva känslan av “tröghet” — appen kan vara funktionellt perfekt, men användaren uppfattar den som långsam på grund av instabil FPS.

Huvudpunkter

  • Jank — överhoppade bildrutor, märkbara som animation hackningar.
  • Huvudorsak — överskridande av tidsbudgeten per bildruta (16.6 ms för 60 FPS).
  • Jank uppstår på grund av tung Layout, lång GC, blockering av main thread eller overdraw.
  • För diagnostik används FrameTimeline (Android) och Instruments (iOS).
  • Åtgärd av Jank ökar NPS och användarbehållning med 15–25%.

Vad är Jank

Jank — är en term från datorgrafik som betecknar en visuell defekt där animationen rör sig ryckigt istället för mjuk glidning. I mobil utveckling mäts Jank som antalet överhoppade bildrutor (skipped frames) per tidsenhet. Om systemet inte hinner förbereda en bildruta till VSync-ögonblicket, upprepar displayen den föregående bildrutan — en paus på 16.6 ms vid 60 Hz uppstår. En överhoppad bildruta kan vara omärkbar, men en serie av 3–5 överhoppade bildrutor i rad skapar en känsla av “tröghet” på 50–80 ms, som användaren tydligt registrerar.

Jank är särskilt kritiskt för animationer som måste fungera med konstant hastighet: scrollning av listor, animationsöppning av meny, parallaxeffekter, övergångar mellan skärmar. Enligt UX-forskning från Google (2024) får en app med Jank-indikator över 3% av scrollsessioner 22% fler enstjärniga recensioner än en app med indikator under 0.5%. Verktyget Android Vitals spårar automatiskt Jank och klassificerar det efter severity: moderate, severe och critical.

Huvudorsaker till Jank

Orsakerna till Jank delas in i flera kategorier. Den första — Layout Jank: orsakas av frekventa requestLayout()-anrop på grund av ändringar i View-storlekar, LayoutTransition-animationer eller dynamisk laddning av innehåll. Varje requestLayout-anrop utlöser Measure + Layout för hela View-subträdet, vilket kan ta 5–30 ms. Den andra — Draw Jank: relaterad till overdraw och användning av tunga drawable. Den tredje — Thread Jank: blockering av main thread på grund av synkrona operationer — filinläsning, arbete med databasen på huvudtråden, avkodning av Bitmap.

Den fjärde kategorin — GC Jank: garbage collection i ART/Dalvik eller Swift ARC. När många objekt samlas på hög, utlöser GC en Stop-The-World-paus på 5–15 ms. På Android uppstår GC-pauser oftast vid frekventa allokeringar i loopar: skapande av objekt i onDraw(), allokeringar i adaptrar, oanvända lambda-uttryck. Den femte — IPC Jank: interprocesskommunikation (ContentProvider, Binder) på huvudtråden. Den sjätte — Rendering Jank: långsam GPU-rendering på grund av icke-optimala shaders eller texturer av stor storlek.

Typ av JankOrsakTypisk varaktighetSökverktyg
LayoutrequestLayout, relayout5–30 msPerfetto, Systrace
DrawOverdraw, tung drawable3–20 msGPU Profiling
ThreadBlockering av main thread10–200 msAndroid Studio Profiler
GCGarbage Collection5–15 msMemory Profiler
RenderingGPU-belastning10–50 msGPU Tracer, Xcode GPU

Diagnostik av Jank i Android

I Android börjar diagnostik av Jank med systemspårning Perfetto. Perfetto registrerar aktivitet för alla trådar, CPU, GPU och schemaläggare. En tydlig indikator på Jank är raderna Choreographer.doFrame och Choreographer.doCallbacks: om intervallet mellan två på varandra följande doFrame-anrop överstiger 16.6 ms, hoppas bildrutan över. Perfetto visar den exakta orsaken — vilket system call, lock eller GC som orsakade fördröjningen. I Android Studio Profiler finns liknande funktionalitet tillgänglig via CPU Profiler.

För automatisk upptäckt av Jank i produktion används FrameMetricsAggregator — ett API som samlar statistik per bildruta och aggregerar per session. I Android 12+ dök PerformanceHintManager upp — ett API för ledtrådar till systemet om målbildfrekvens. Om appen anger att den arbetar i ett 120 FPS-scenario, kan systemet öka CPU/GPU-frekvensen för att förhindra Jank. För enkel loggning av alla överhoppade bildrutor räcker det att prenumerera på Choreographer.FrameCallback.

Logga Jank via Choreographer

Kotlin-kod prenumererar på Choreographer.FrameCallback och loggar varje överhoppad bildruta med angivelse av fördröjningens längd. Callback anropas vid varje VSync.

kotlin
class JankDetector {

    private val frameBudget = 16_666_666L
    private var previousFrameTime = 0L

    private val callback =
        Choreographer.FrameCallback { currentTime ->
            if (previousFrameTime != 0L) {
                val frameDuration =
                    currentTime - previousFrameTime
                val skippedFrames =
                    (frameDuration / frameBudget) - 1
                if (skippedFrames > 0) {
                    Log.w("Jank",
                        "$skippedFrames bildrutor hoppades över")
                }
            }
            previousFrameTime = currentTime
            Choreographer.getInstance()
                .postFrameCallback(this)
        }

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

Diagnostik av Jank i iOS

I iOS utförs diagnostik av Jank via Instruments med Core Animation-mallen. Instruments visar FPS i realtid, antalet offscreen-renderingar och hit-tester. Huvudindikatorer för Jank i iOS: röda kolumner på Core Animation-tidsskalan (överskridande av bildrutebudget), hög Renderer-indikator (betyder offscreen rendering) och låg FPS. För produktionsövervakning samlar MetricKit rapporter med metriken MXAnimatoryMetric, som inkluderar genomsnittlig FPS, P50 och P95 bildrutetid.

Native diagnostik av Jank i iOS inkluderar CADisplayLink med kontroll av timestamp och targetTimestamp. Om den aktuella timestamp ligger betydligt efter targetTimestamp, har en eller flera bildrutor hoppats över. Apple rekommenderar också att använda os_signpost för anpassad profilering: placera signpost-intervall i början och slutet av bildruterendering och kontrollera i Instruments vilka intervall som överstiger 16.6 ms. I SwiftUI för Jank-diagnostik används UIView.invalidateIntrinsicContentSize — frekvent anrop av denna metod indikerar instabil Layout.

CADisplayLink för Jank-detektion

Swift-kod bestämmer överhoppade bildrutor via CADisplayLink. Om skillnaden mellan timestamp och targetTimestamp överstiger 16.6 ms — registreras Jank.

swift
class JankMonitor {

    private var displayLink: CADisplayLink?
    private var totalJank = 0

    func start() {
        displayLink = CADisplayLink(
            target: self,
            selector: #selector(detectJank)
        )
        displayLink?.add(to: .current,
            forMode: .common)
    }

    @objc
    private func detectJank() {
        guard let link = displayLink else { return }
        let delay = link.targetTimestamp
            - link.timestamp
        if delay > 0.0167 {
            totalJank += 1
        }
    }
}

Jank-profileringsverktyg

För profilering av Jank används både inbyggda OS-verktyg och tredjeparts-SDK:er. I Android är det viktigaste verktyget Perfetto (ersatte Systrace). Perfetto möjliggör inspelning av spårningar upp till 30 sekunder och analys via webbgränssnittet ui.perfetto.dev. Det visar en exakt tidslinje med aktivitet av Choreographer, renderingstrådar (RenderThread) och GPU. För detaljerad analys av GPU-problem används AGI (Android GPU Inspector), som inte bara visar bildrutetid utan även belastningen på specifika GPU-block — shaders, rasterizer, texturblock.

I iOS är motsvarigheten Instruments med mallarna Core Animation, Metal System Trace och GPU Driver. Core Animation visar FPS och bildrutetid, Metal System Trace — GPU-arbete med detalj ner till varje draw call. För profilering på riktiga enheter under belastning används Firebase Performance (samlar Screen Rendering-metrik) och Sentry(fångar stack trace vid Jank). Det nya Android 15 Performance Hint API låter utvecklaren indikera för systemet vilka bildrutor som är viktiga och få varningar från systemet när Jank närmar sig.

FrameMetricsAggregator i produktion

Kotlin-kod använder FrameMetricsAggregator för att samla bildrutestatistik per session. Efter att aggregatorn stoppats visas antalet överhoppade bildrutor.

kotlin
class JankAggregator(private val activity: Activity) {

    private val aggregator = FrameMetricsAggregator()

    fun startCollection() {
        aggregator.add(activity.window)
    }

    fun stopAndReport() {
        aggregator.remove()
        val result = aggregator.getMetrics()
        val totalFrames = result
            ?.get(FrameMetrics.TOTAL_DURATION)
            ?.size ?: 0
        val jankFrames = result
            ?.get(FrameMetrics.TOTAL_DURATION)
            ?.count { it > 16_666_666L} ?: 0
        Log.d("JankReport",
            "Jank-förhållande: ${jankFrames * 100 / totalFrames}%")
    }
}

Metoder för att åtgärda ram hackningar

Åtgärd av Jank kräver en kombination av metoder beroende på typ. För Layout Jank: ersätt djupa hierarkier med ConstraintLayout/Compose/SwiftUI, använd merge-taggar, undvik requestLayout i animationer. För Draw Jank: använd Debug GPU Overdraw för att hitta 4x+ overdraw, ersätt tunga drawable med vektor (VectorDrawable/PDF), använd hardware layers försiktigt — de accelererar rendering men förbrukar mer GPU-minne. För Thread Jank: flytta alla I/O-operationer, databasarbete och Bitmap-avkodning till bakgrundstrådar, använd Kotlin Coroutines med rätt Dispatcher eller RxJava med Schedulers.io().

För GC Jank: minimera allokeringar i onDraw() och getView(), använd objektpooler (ObjectPool), ersätt for-each med indexerad for, använd immutable data class i Kotlin med copy() försiktigt — copy skapar ett nytt objekt. För IPC Jank: lat initialisering av ContentProvider via App Startup, flytta Binder-anrop till bakgrundstråd. För Rendering Jank: minska texturstorleken till skärmens maximala upplösning, använd ASTC eller ETC2-komprimering, undvik onödig shader compilation (kompilera shaders i förväg). Komplett lösning — regelbunden Perfetto/Instruments-profilering i CI och spårning av Jank-regressioner.

Anti-Jank-mönster: Async Layout

Kotlin-kod demonstrerar asynkron laddning av data på skärmen efter reportFullyDrawn, så att tungt arbete inte blockerar den första bildrutan. Callback anropas efter att användaren ser gränssnittet.

kotlin
class JankSafeLoader {

    suspend fun loadAfterFirstFrame(
        activity: Activity
    ) {
        // garanterar att den första bildrutan redan är renderad
        if (Build.VERSION.SDK_INT >= 29) {
            activity.reportFullyDrawn()
        }

        // tung laddning — efter första bildrutan
        withContext(Dispatchers.IO) {
            val data = fetchHeavyData()
            withContext(Dispatchers.Main) {
                updateUI(data)
            }
        }
    }
}

Vanliga frågor

Vad är Jank i mobilappar?

Jank — är överhoppade renderingsbildrutor som visar sig som märkbara hackningar eller ryck i animering. Uppstår när förberedelsetiden för en bildruta överskrider tidsbudgeten (16.6 ms för 60 FPS).

Vilka är huvudorsakerna till Jank?

Layout Jank (frekventa requestLayout), Draw Jank (overdraw), Thread Jank (blockering av main thread), GC Jank (garbage collection), IPC Jank (Binder-anrop) och Rendering Jank (tunga shaders).

Hur diagnostiserar man Jank i Android?

Använd Perfetto för systemspårning, GPU Profiling för analys av bildrutefaser och FrameMetricsAggregator för produktionsövervakning. I Android Studio — CPU Profiler med Deep Java Trace.

Hur mäter man Jank i iOS?

Via Instruments med Core Animation- eller Metal System Trace-mallen. För produktion — MetricKit med MXAnimatoryMetric. Programmatiskt — CADisplayLink med kontroll av skillnaden mellan timestamp och targetTimestamp.

Vilken procentandel Jank anses vara kritisk?

Enligt Google leder en Jank-indikator över 3% av scrollsessioner (3 av 100 scrollningar innehåller hackning) till en ökning av negativa recensioner med 22%. Målindikator — mindre än 0.5% av scrollsessioner.

Sammanfattning

  • Jank — överhoppade bildrutor som orsakar synliga animations hackningar i mobilappar.
  • Huvudorsaker: Layout Jank, Draw Jank, Thread Jank, GC Jank, IPC Jank och Rendering Jank.
  • Jank-diagnostik i Android — via Perfetto, GPU Profiling och FrameMetricsAggregator.
  • Jank-diagnostik i iOS — via Instruments, CADisplayLink och MetricKit.
  • Åtgärd av Jank kräver en kombination: platta hierarkier, bakgrundstrådar, minimala allokeringar, cachning.
  • Mål Jank-indikator — mindre än 0.5% av scrollsessioner med hackningar.
  • Regelbunden profilering i CI förhindrar prestandaregressioner innan de når produktion.

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å