Warm Start: essentie, warme start en optimalisatie in Android

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

Warm Start is een opstartscenario van een Android-app waarbij het proces van de app al in het geheugen bestaat (bijvoorbeeld na minimaliseren), maar de Activity door het systeem is vernietigd om bronnen te besparen. Application.onCreate is al uitgevoerd, klassen zijn geladen, maar de UI wordt opnieuw aangemaakt. Volgens Google, 2024 duurt Warm Start 200 tot 800 ms en vormt ongeveer 40% van alle starts op apparaten met 4 GB RAM.

Belangrijkste punten

  • Warm Start — start van een app met een bestaand proces maar zonder Activity in het geheugen
  • Verschil met Cold Start: Application.onCreate wordt niet uitgevoerd, klassen zijn al geladen
  • Tijd Warm Start is 200–800 ms tegenover 1–5 seconden voor Cold Start
  • Scenario's: terugkeer naar de app na enkele uren, verwijdering van Activity door OOM-killer
  • Optimalisatie richt zich op het behouden van de Activity-status en het cachen van gegevens

Wat is Warm Start

Warm Start (warme start) is een toestand tussen Cold Start en Hot Start: het proces van de app bestaat in het geheugen (soms in de Linux-achtergrondcache), maar de Activity is niet actief en wordt opnieuw aangemaakt. Het Android-systeem kan bij gebrek aan RAM de Activity uit de stack verwijderen terwijl het proces in leven blijft. Wanneer de gebruiker terugkeert naar de app, begint Warm Start: een nieuw exemplaar van Activity wordt aangemaakt, de lifecycle-methoden onCreate → onStart → onResume worden uitgevoerd, maar Application.onCreate en het laden van klassen worden overgeslagen.

Oorzaken van Warm Start

Het Android-systeem beslist over het verwijderen van Activity op basis van de procesprioriteit (importance rank). Activity op de achtergrond (niveau PROCESS_STATE_IMPORTANT_FOREGROUND of PROCESS_STATE_TOP_SLEEPING) kan 5–30 minuten na het minimaliseren van de app worden vernietigd, afhankelijk van het beschikbare RAM. Op apparaten met 3 GB RAM kan Activity na 10 minuten worden verwijderd, op apparaten met 8 GB — na enkele uren. Belangrijk: bij Warm Start wordt onSaveInstanceState aangeroepen vóór vernietiging van Activity en kan de ontwikkelaar de UI-status opslaan.

Gebruikersperceptie

De gebruiker ziet geen verschil tussen Warm en Cold Start — hij klikt gewoon op het app-pictogram en wacht. Bij Warm Start kan echter een wit scherm (blank window) verschijnen als de app geen eigen thema voor het startvenster heeft ingesteld. Google raadt aan een aangepast thema in het manifest in te stellen (Theme.AppCompat.Light of Theme.Material3.DayNight) voor de start-Activity om flikkeren van wit/zwart scherm bij Warm Start te voorkomen. Op Android 12+ verbergt SplashScreen API dit effect ook.

Warm Start vs Cold Start vs Hot Start

Inzicht in het verschil tussen de drie typen starts is nodig voor het kiezen van de juiste profilering- en optimalisatiestrategie. Elk type heeft zijn eigen duur, knelpunten en meetinstrumenten.

CriteriumCold StartWarm StartHot Start
ProcesOpnieuw aangemaaktBestaat in geheugenBestaat in geheugen
Application.onCreateWordt uitgevoerdWordt niet uitgevoerdWordt niet uitgevoerd
ActivityVanaf nul aangemaaktVanaf nul aangemaaktHersteld uit stack
Tijd1–5 seconden200–800 ms< 200 ms
onCreate ActivityVolledigVolledig (met restore)Overgeslagen

In de praktijk vormt Warm Start 30% tot 60% van alle app-starts, afhankelijk van gebruikersgewoonten en de hoeveelheid RAM van het apparaat. Gebruikers die veel apps open houden (multitaskers) krijgen vaker met Warm Start te maken. Voor sociale netwerken en messengers is Warm Start het meest voorkomende scenario omdat de app altijd op de achtergrond draait. Voor bankapps daarentegen overheerst Cold Start (gedwongen procesopschoning om veiligheidsredenen).

Fasen van warme start

Warm Start bestaat uit drie fasen, die elk kunnen worden gemeten en geoptimaliseerd. In tegenstelling tot Cold Start is er hier geen fork-fase en het laden van klassen, maar er is een herstelfase (restore) die kostbaar kan zijn.

Fase 1: Startvenster (window background)

Het systeem controleert of de app een thema heeft voor het startvenster. Als er geen thema is ingesteld, wordt een wit (of zwart, afhankelijk van het systeem) scherm weergegeven. Als er een thema is ingesteld, wordt de achtergrond uit het thema weergegeven. Deze fase duurt 10–30 ms, maar is visueel voelbaar als het thema niet overeenkomt met de werkelijke UI van de app. Gebruik Theme.Material3.DayNight met een aangepaste windowBackground waarvan de kleur overeenkomt met de achtergrond van het eerste scherm — dit creëert een effect van onmiddellijk laden.

Fase 2: Activity aanmaken (herstel)

Het systeem roept onCreate aan met Bundle savedInstanceState die was opgeslagen in onSaveInstanceState vóór vernietiging van Activity. Als de app de status correct heeft opgeslagen (veldtekst, scrollpositie, ViewModel-gegevens), verloopt het herstel snel. Zo niet — dan begint Activity met een lege pagina en ziet de gebruiker een loader tot de gegevens zijn geladen. Belangrijk punt: ViewModel-objecten overleven Warm Start alleen als het proces niet is vernietigd — bij Warm Start blijft ViewModel in het geheugen.

Fase 3: Eerste frame (TTFD)

Na onCreate worden onStart → onResume uitgevoerd en roept het systeem de eerste weergave aan. TTFD (Time To First Draw) voor Warm Start moet minder dan 300 ms zijn op een gemiddeld apparaat. Als het eerste scherm een complexe RecyclerView met zware Views bevat of afbeeldingen via het netwerk laadt, kan TTFD de drempel overschrijden. Gebruik Placeholder en Shimmer voor soepel laden van content na het eerste frame.

Hoe Warm Start meten

Het meten van Warm Start is complexer dan Cold Start omdat u de toestand «proces leeft, Activity vernietigd» moet simuleren. Het standaard ADB-commando met de vlag -S is niet geschikt — het doodt het proces. Gebruik voor Warm Start andere benaderingen.

ADB shell am start zonder -S

Start eerst de app via adb shell monkey of tik op het pictogram, minimaliseer deze vervolgens (adb shell input keyevent 3 keyevent HOME). Wacht 5–10 seconden zodat het systeem de Activity kan verwijderen en voer adb shell am start -W (zonder -S) uit. Het commando geeft de starttijd terug die korter zal zijn dan Cold Start. Gebruik voor reproduceerbaarheid een script: start → wacht → home → wacht → start.

bash
# Simulatie van Warm Start via ADB
$ adb shell am start -W \
    com.example.app/.MainActivity

# Uitvoer (Warm Start):
# ThisTime: 412 ms
# TotalTime: 412 ms
# WaitTime: 423 ms

Macrobenchmark voor Warm Start

De bibliotheek androidx.benchmark.macro ondersteunt het meten van Warm Start. Stel hiervoor in de test startupMode = StartupMode.WARM in — de bibliotheek start de app, minimaliseert deze, wacht (configureerbare vertraging) en meet vervolgens de herstart. Macrobenchmark voert 10–20 runs uit en berekent percentielen. In CI/CD kunt u een drempel instellen: als P50 Warm Start 600 ms overschrijdt — faalt de test. Dit maakt het mogelijk regressies bij elke commit te volgen.

Firebase Performance Monitoring

Firebase onderscheidt automatisch Cold en Warm Start op basis van de tijd sinds de vorige sluiting van de app. Als de app in de laatste 30 minuten is geopend, classificeert Firebase de start als Warm. In de Firebase-console ziet u aparte grafieken voor elk starttype, waarmee u de effectiviteit van optimalisaties kunt evalueren. Na implementatie van statusopslag in ViewModel kunt u bijvoorbeeld een verlaging van Warm Start met 30% zien.

Warm Start optimaliseren

Optimalisatie van Warm Start richt zich op twee gebieden: het versnellen van Activity.onCreate en het correct herstellen van de status. Omdat Application.onCreate en het laden van klassen al zijn uitgevoerd, is het belangrijkste knelpunt de UI-code van het eerste scherm.

Asynchroon herstel van status

Als de opgeslagen status (savedInstanceState) gegevens bevat die gedeserialiseerd moeten worden (Bitmap, String, JSON), doe dit dan op de achtergrond. In plaats van direct uit Bundle te lezen in onCreate, start u een coroutine en toont u een shimmer-scherm. In de praktijk duurt deserialisatie van Bundle op een gemiddeld apparaat 20–100 ms — lijkt weinig, maar voor Warm Start is dit 10–50% van de totale tijd. Gebruik de Saved State Module van de Jetpack-bibliotheek die automatisch de ViewModel-status opslaat en herstelt in Bundle of database.

Optimalisatie van setContentView

Het opblazen van XML-layout (layout inflation) is een van de duurste stappen van Warm Start. Als het eerste scherm een complexe CoordinatorLayout gebruikt met AppBar, CollapsingToolbar, NestedScrollView plus drie RecyclerViews, kan de inflatietijd 300 ms bereiken. Oplossingen: gebruik ConstraintLayout voor een platte hiërarchie, pas ViewStub toe voor bij start onzichtbare secties (bottom sheet, dialog), schakel asynchroon opblazen voor zware fragmenten in via AsyncLayoutInflater. In Jetpack Compose is inflation niet nodig, maar het compileren van de Compose-boom bij Warm Start kan vergelijkbare tijd kosten.

Gegevens cachen

Bij Warm Start kunnen gegevens die de app in de vorige sessie heeft geladen al in de cache zitten: Room-database, SharedPreferences, in-memory cache in ViewModel. Als uw eerste scherm een lijst van de server toont, controleer dan de cache bij start en werk de gegevens op de achtergrond bij. Gebruik de strategie cache-then-network: toon eerst de gecachte gegevens (onmiddellijk), werk vervolgens bij vanaf de server (asynchroon). Dit verkort de waargenomen tijd van Warm Start tot 100–200 ms.

kotlin
// ViewModel met caching voor Warm Start
class FeedViewModel : ViewModel() {
    private val cache = MutableStateFlow<List<Item>>(emptyList())

    init {
        // Eerst cache, dan netwerk
        viewModelScope.launch {
            cache.emit(db.getItems()) // Warm Start: gegevens al in database
            cache.emit(api.fetchItems()) // Achtergrondupdate
        }
    }
}

Status behouden bij Warm Start

Correcte statusopslag is de sleutelfactor die een goede Warm Start onderscheidt van een slechte. De gebruiker verwacht terug te keren naar de app en hetzelfde te zien als wat hij heeft achtergelaten — inclusief scrollpositie, tekst in velden, geselecteerde tabbladen.

onSaveInstanceState

Het systeem roept onSaveInstanceState aan bij vernietiging van Activity, maar VOORDAT het proces kan worden gedood. In Bundle worden alleen eenvoudige gegevens opgeslagen (String, Int, Parcelable, Serializable). Gebruik voor complexe gegevens SavedStateHandle in ViewModel — het slaat automatisch velden op en herstelt ze bij Warm Start. In tegenstelling tot onSaveInstanceState werkt SavedStateHandle zelfs als het proces Warm Start heeft overleefd (ViewModel wordt niet vernietigd). Voorbeeld: gebruik voor tekst in EditText SavedStateHandle.getLiveData(«text») — de tekst wordt automatisch opgeslagen en hersteld.

ViewModel en Warm Start

Als bij Warm Start het proces niet is gedood, blijft ViewModel in het geheugen en wordt onCleared niet aangeroepen. Dit betekent dat alle in de vorige sessie geladen gegevens onmiddellijk beschikbaar zijn. Maar als het proces is gedood (apparaat in deep sleep langer dan 30 minuten), wordt ViewModel vernietigd en opnieuw aangemaakt met SavedStateHandle. Voor correct werken van ViewModel bij Warm Start gebruikt u SavedStateHandle met velden die in elk scenario moeten worden hersteld. Verschil: ViewModel met @HiltViewModel ondersteunt SavedStateHandle automatisch.

MechanismeProces leeftProces gedood
ViewModelGegevens in geheugenVernietigd, opnieuw aangemaakt
SavedStateHandleGegevens in geheugenHersteld uit Bundle
onSaveInstanceStateAangeroepen bij verwijdering ActivityNiet aangeroepen
Room DBCache beschikbaarCache beschikbaar (schijf)

Scrollpositie RecyclerView behouden

Een van de meest voorkomende problemen bij Warm Start — verlies van scrollpositie. De gebruiker heeft door de feed naar het 50e element gescrolld, de app geminimaliseerd, keerde terug — en ziet het begin van de lijst. Oplossing: sla layoutManager.onSaveInstanceState op (bewaart positie en offset van het eerste zichtbare element) en herstel het in onRestoreInstanceState. U kunt ook de laatste zichtbare positie opslaan in SharedPreferences met een datum/tijd-sleutel om bij Warm Start snel de positie te herstellen.

kotlin
// Scrollpositie RecyclerView behouden
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putParcelable(
        "rv_state", binding.recyclerView
            .layoutManager?.onSaveInstanceState()
    )
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    savedInstanceState?.getParcelable<Parcelable>("rv_state")
        ?.let { binding.recyclerView.layoutManager?.onRestoreInstanceState(it) }
}

Codevoorbeelden voor Warm Start

Twee praktische voorbeelden van Warm Start-optimalisatie: gebruik van SavedStateHandle in ViewModel en asynchroon herstel van complexe gegevens na de start.

ViewModel met SavedStateHandle

SavedStateHandle slaat automatisch velden op in Bundle en herstelt ze bij Warm Start. Het gebruikersprofielveld (String, JSON) wordt hersteld zonder extra serververzoeken. Als het proces is gedood, laadt SavedStateHandle de laatst opgeslagen status uit Bundle.

kotlin
class ProfileViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    val profile: StateFlow<Profile?>
        get() = savedStateHandle
            .getStateFlow("profile", null)

    fun loadProfile(id: String) {
        viewModelScope.launch {
            savedStateHandle["profile"] =
                api.getProfile(id)
        }
    }
}

// Warm Start: profile is niet null, UI zonder loader
// Na laden: profile wordt bijgewerkt in SavedStateHandle

AsyncLayoutInflater voor zwaar scherm

Als het eerste scherm een complexe layout bevat (kaart, verloop, meerdere lijsten), gebruik dan AsyncLayoutInflater voor het opblazen van zware elementen op de achtergrond. Terwijl de layout wordt opgeblazen, toon een placeholder met shimmer-effect. Dit is vooral belangrijk voor Warm Start, waar elke milliseconde telt. AsyncLayoutInflater werkt op de achtergrond en levert de kant-en-klare View via callback aan de hoofdthread.

kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Placeholder-layout voor onmiddellijke weergave
        setContentView(R.layout.placeholder_shimmer)

        // Asynchroon laden van zware layout
        AsyncLayoutInflater(this).inflate(
            R.layout.activity_main_complex,
            findViewById(R.id.container)
        ) { view, resId, parent ->
            parent?.removeAllViews()
            parent?.addView(view)
        }
    }
}

Veelgestelde vragen

Kan Warm Start overgaan in Cold Start?

Ja, als het systeem op het moment van Warm Start besluit het app-proces te doden (bijvoorbeeld om geheugen vrij te maken voor een andere app), wordt de start een Cold Start vanaf nul. Dit gebeurt op apparaten met 2–3 GB RAM bij gelijktijdig gebruik van meerdere apps. In de praktijk is Warm Start slechts 10–20 minuten na minimaliseren gegarandeerd op middenklasse apparaten.

Blijft ViewModel behouden bij Warm Start?

Ja, als het proces niet is gedood, blijft ViewModel in het geheugen en wordt onCleared niet aangeroepen. Dit is het belangrijkste voordeel van Warm Start: alle geladen gegevens, netwerkverzoeken, cache in ViewModel — onmiddellijk beschikbaar. Als het proces is gedood, wordt ViewModel opnieuw aangemaakt via ViewModelProvider.Factory of @HiltViewModel en herstelt SavedStateHandle de opgeslagen velden.

Waarom kan Warm Start langzamer zijn dan Cold Start?

Theoretisch is Warm Start altijd sneller dan Cold Start, maar in de praktijk zijn er scenario's waarin het verschil minimaal is: als Application.onCreate licht (50 ms) en Activity.onCreate zwaar (800 ms) is, dan is Warm Start (800 ms) bijna gelijk aan Cold Start (850 ms). In dit geval moet niet Application, maar Activity.onCreate worden geoptimaliseerd — dat wordt het knelpunt voor Warm Start.

Hoe beïnvloedt SplashScreen API Warm Start?

SplashScreen API op Android 12+ toont een systeemsplash (pictogram op gekleurde achtergrond) onmiddellijk bij start — zowel voor Cold als Warm Start. Voor Warm Start wordt de splash slechts 100–300 ms weergegeven, waarna deze wordt vervangen door de app-UI. SplashScreen versnelt de start zelf niet, maar maskeert de tijd van Activity-creatie en verbetert de perceptie.

Moet ik Warm Start optimaliseren als Cold Start al snel is?

Ja, omdat Warm Start 2–3 keer vaker voorkomt dan Cold Start. Als Cold Start 1,2 seconden duurt en Warm Start 600 ms, dan duren 40% van de starts (Warm) nog steeds 0,6 seconden, wat voelbaar is. Optimalisatie van Warm Start tot 200–300 ms geeft de gebruiker het gevoel van onmiddellijke terugkeer. Op apparaten met 6+ GB RAM kan Warm Start tot 80% van alle starts uitmaken en wordt optimalisatie een prioriteit.

Samenvatting

  • Warm Start — start met bestaand proces, zonder Activity in geheugen, tijd 200–800 ms
  • Belangrijkste verschil met Cold Start: Application.onCreate wordt niet uitgevoerd, klassen zijn geladen
  • Drie fasen van Warm Start: startvenster → Activity aanmaken → eerste frame
  • Gemeten via ADB zonder vlag -S of Macrobenchmark met StartupMode.WARM
  • Optimalisatie: SavedStateHandle, AsyncLayoutInflater, cache-then-network, ConstraintLayout
  • ViewModel blijft behouden bij Warm Start (levend proces) — gegevens onmiddellijk beschikbaar
  • Warm Start vormt 40–80% van alle app-starts

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