Warm Start: lényege, meleg indítás és optimalizálás Androidban

Szerző: IT Sectr Megjelenés: 2026-03-31 Olvasási idő: 8 perc

Warm Start egy Android-alkalmazás indítási forgatókönyve, ahol az alkalmazás folyamata már létezik a memóriában (például minimalizálás után), de az Activity-t a rendszer megsemmisítette az erőforrások megtakarítása érdekében. Az Application.onCreate már lefutott, az osztályok betöltődtek, de az UI újra létrejön. A Google, 2024 szerint a Warm Start 200–800 ms-ig tart, és a 4 GB RAM-mal rendelkező eszközökön az összes indítás körülbelül 40%-át teszi ki.

Főbb pontok

  • Warm Start — alkalmazás indítása meglévő folyamattal, de Activity nélkül a memóriában
  • Különbség a Cold Start-tól: Az Application.onCreate nem fut le, az osztályok már betöltődtek
  • Idő Warm Start: 200–800 ms vs Cold Start: 1–5 másodperc
  • Forgatókönyvek: visszatérés az alkalmazáshoz órák után, Activity kitöltése OOM-killer által
  • Optimalizálás az Activity állapotának megőrzésére és az adatok gyorsítótárazására összpontosít

Mi az a Warm Start

Warm Start (meleg indítás) a Cold Start és Hot Start közötti állapot: az alkalmazás folyamata létezik a memóriában (néha a Linux háttér-gyorsítótárban), de az Activity nem aktív, és újra létrejön. Az Android rendszer RAM hiányában kitöltheti az Activity-t a veremből, miközben a folyamat életben marad. Amikor a felhasználó visszatér az alkalmazáshoz, elindul a Warm Start: létrejön az Activity új példánya, lefutnak az életciklus-metódusok onCreate → onStart → onResume, de az Application.onCreate és az osztályok betöltése kimarad.

A Warm Start okai

Az Android rendszer a folyamat prioritása (importance rank) alapján dönt az Activity kitöltéséről. A háttérben lévő Activity (PROCESS_STATE_IMPORTANT_FOREGROUND vagy PROCESS_STATE_TOP_SLEEPING szint) 5–30 perccel az alkalmazás minimalizálása után megsemmisíthető, a rendelkezésre álló RAM-tól függően. A 3 GB RAM-mal rendelkező eszközökön az Activity 10 perc után kitölthető, a 8 GB-os eszközökön — órák után. Fontos: Warm Start esetén az onSaveInstanceState az Activity megsemmisítése előtt kerül meghívásra, és a fejlesztő elmentheti az UI állapotát.

Felhasználói észlelés

A felhasználó nem lát különbséget a Warm és Cold Start között — csak megnyomja az alkalmazás ikonját és vár. Azonban Warm Start esetén megjelenhet egy fehér képernyő (blank window), ha az alkalmazás nem állított be saját témát a kezdő ablakhoz. A Google azt javasolja, hogy állítson be egyedi témát a manifest-ben (Theme.AppCompat.Light vagy Theme.Material3.DayNight) a kezdő Activity-hez a fehér/fekete képernyő villogásának elkerülése érdekében Warm Start esetén. Android 12+ rendszeren a SplashScreen API is elrejti ezt a hatást.

Warm Start vs Cold Start vs Hot Start

A három indítási típus közötti különbség megértése szükséges a megfelelő profilozási és optimalizálási stratégia kiválasztásához. Minden típusnak megvan a saját időtartama, saját szűk keresztmetszetei és saját mérőeszközei.

KritériumCold StartWarm StartHot Start
FolyamatÚjra létrejönLétezik a memóriábanLétezik a memóriában
Application.onCreateLefutNem fut leNem fut le
ActivityNulláról létrejönNulláról létrejönVisszaáll a veremből
Idő1–5 másodperc200–800 ms< 200 ms
onCreate ActivityTeljesTeljes (restore-al)Kimarad

A gyakorlatban a Warm Start az összes alkalmazásindítás 30–60%-át teszi ki, a felhasználói szokásoktól és az eszköz RAM mennyiségétől függően. Azok a felhasználók, akik sok alkalmazást tartanak nyitva (multitasker), gyakrabban találkoznak Warm Start-tal. A közösségi hálózatok és üzenetküldők esetében a Warm Start a leggyakoribb forgatókönyv, mivel az alkalmazás mindig a háttérben fut. A banki alkalmazásoknál ezzel szemben a Cold Start dominál (a folyamat kényszerű tisztítása biztonsági okokból).

A meleg indítás fázisai

A Warm Start három fázisból áll, amelyek mindegyike mérhető és optimalizálható. A Cold Start-tól eltérően itt nincs fork fázis és osztálybetöltés, de van állapot-visszaállítási fázis (restore), amely költséges lehet.

1. fázis: Kezdő ablak (window background)

A rendszer ellenőrzi, hogy az alkalmazásnak van-e témája a kezdő ablakhoz. Ha nincs téma beállítva, fehér (vagy fekete, a rendszertől függően) képernyő jelenik meg. Ha van téma beállítva, a témából származó háttér jelenik meg. Ez a fázis 10–30 ms-ig tart, de vizuálisan érezhető, ha a téma nem egyezik az alkalmazás valós UI-jával. Használja a Theme.Material3.DayNight témát egyedi windowBackground-del, amelynek színe megegyezik az első képernyő hátterével — ez azonnali betöltés hatását kelti.

2. fázis: Activity létrehozása (visszaállítás)

A rendszer meghívja az onCreate-t a Bundle savedInstanceState átadásával, amely az onSaveInstanceState-ban lett elmentve az Activity megsemmisítése előtt. Ha az alkalmazás helyesen mentette el az állapotot (mezőszöveg, görgetési pozíció, ViewModel adatok), a visszaállítás gyorsan megtörténik. Ha nem — az Activity üres lapról indul, és a felhasználó loader-t lát, amíg az adatok betöltődnek. Kulcspont: a ViewModel objektumok csak akkor élik túl a Warm Start-ot, ha a folyamat nem semmisült meg — Warm Start esetén a ViewModel a memóriában marad.

3. fázis: Első képkocka (TTFD)

Az onCreate után lefut az onStart → onResume, és a rendszer meghívja az első megjelenítést. A TTFD (Time To First Draw) Warm Start esetén kevesebb mint 300 ms kell legyen egy közepes eszközön. Ha az első képernyő összetett RecyclerView-t tartalmaz nehéz View-kkal vagy képeket tölt be a hálózaton keresztül, a TTFD túllépheti a küszöbértéket. Használjon Placeholder-t és Shimmer-t a tartalom zökkenőmentes betöltéséhez az első képkocka után.

Hogyan mérjük a Warm Start-ot

A Warm Start mérése bonyolultabb, mint a Cold Start-é, mert szimulálni kell a «a folyamat él, az Activity megsemmisült» állapotot. A szabványos ADB parancs a -S jelzővel nem megfelelő — megöli a folyamatot. Warm Start esetén más megközelítéseket használjon.

ADB shell am start -S nélkül

Először indítsa el az alkalmazást az adb shell monkey-n keresztül vagy koppintson az ikonra, majd minimalizálja (adb shell input keyevent 3 keyevent HOME). Várjon 5–10 másodpercet, hogy a rendszer kitölthesse az Activity-t, majd futtassa az adb shell am start -W parancsot (-S nélkül). A parancs visszaadja az indítási időt, amely rövidebb lesz, mint a Cold Start. A reprodukálhatóság érdekében használjon szkriptet: indítás → várakozás → home → várakozás → indítás.

bash
# Warm Start szimulálása ADB-n keresztül
$ adb shell am start -W \
    com.example.app/.MainActivity

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

Macrobenchmark Warm Start-hoz

Az androidx.benchmark.macro könyvtár támogatja a Warm Start mérését. Ehhez a tesztben állítsa be a startupMode = StartupMode.WARM értéket — a könyvtár elindítja az alkalmazást, minimalizálja, vár (konfigurálható késleltetés), majd megméri az újraindítást. A Macrobenchmark 10–20 futtatást végez és percentiliseket számol. A CI/CD-ben küszöbértéket állíthat be: ha a P50 Warm Start meghaladja a 600 ms-t — a teszt megbukik. Ez lehetővé teszi a regressziók nyomon követését minden commit-nál.

Firebase Performance Monitoring

A Firebase automatikusan megkülönbözteti a Cold és Warm Start-ot az alkalmazás előző bezárása óta eltelt idő alapján. Ha az alkalmazás az elmúlt 30 percben meg volt nyitva, a Firebase Warm-ként osztályozza az indítást. A Firebase konzolban külön grafikonokat fog látni minden indítási típushoz, lehetővé téve az optimalizálások hatékonyságának értékelését. Például az állapotmentés ViewModel-ben történő bevezetése után a Warm Start 30%-os csökkenését figyelheti meg.

Warm Start optimalizálása

A Warm Start optimalizálása két irányra összpontosít: az Activity.onCreate felgyorsítása és az állapot helyes visszaállítása. Mivel az Application.onCreate és az osztálybetöltés már megtörtént, a fő szűk keresztmetszet az első képernyő UI kódja.

Aszinkron állapot-visszaállítás

Ha a mentett állapot (savedInstanceState) olyan adatokat tartalmaz, amelyeket deszerializálni kell (Bitmap, String, JSON), ezt háttérszálon végezze. Ahelyett, hogy közvetlenül a Bundle-ből olvasna az onCreate-ben, indítson el egy coroutine-t és jelenítsen meg egy shimmer képernyőt. A gyakorlatban a Bundle deszerializálása egy közepes eszközön 20–100 ms-ig tart — kevésnek tűnik, de Warm Start esetén ez a teljes idő 10–50%-a. Használja a Jetpack könyvtár Saved State Module modulját, amely automatikusan elmenti és visszaállítja a ViewModel állapotát Bundle-ben vagy adatbázisban.

A setContentView optimalizálása

Az XML elrendezés kiterjesztése (layout inflation) a Warm Start egyik legköltségesebb lépése. Ha az első képernyő összetett CoordinatorLayout-ot használ AppBar-rel, CollapsingToolbar-rel, NestedScrollView-val és három RecyclerView-val, az inflation idő elérheti a 300 ms-t. Megoldások: használjon ConstraintLayout-ot lapos hierarchiához, alkalmazza a ViewStub-ot a kezdetben nem látható szakaszokhoz (bottom sheet, dialog), kapcsolja be az aszinkron kiterjesztést nehéz fragmentumokhoz az AsyncLayoutInflater segítségével. A Jetpack Compose-ban nincs szükség inflation-re, de a Compose fa fordítása Warm Start esetén hasonló időt vehet igénybe.

Adatok gyorsítótárazása

Warm Start esetén az alkalmazás által az előző munkamenetben betöltött adatok már lehetnek a gyorsítótárban: Room adatbázis, SharedPreferences, in-memory cache a ViewModel-ben. Ha az első képernyő egy lista a szerverről, ellenőrizze a gyorsítótárat indításkor és frissítse az adatokat a háttérben. Használja a cache-then-network stratégiát: először jelenítse meg a gyorsítótárazott adatokat (azonnal), majd frissítse a szerverről (aszinkron). Ez csökkenti a Warm Start észlelt idejét 100–200 ms-ra.

kotlin
// ViewModel gyorsítótárazással Warm Start-hoz
class FeedViewModel : ViewModel() {
    private val cache = MutableStateFlow<List<Item>>(emptyList())

    init {
        // Először gyorsítótár, aztán hálózat
        viewModelScope.launch {
            cache.emit(db.getItems()) // Warm Start: adatok már az adatbázisban
            cache.emit(api.fetchItems()) // Frissítés a háttérben
        }
    }
}

Állapot megőrzése Warm Start esetén

Az állapot helyes mentése az a kulcstényező, amely megkülönbözteti a jó Warm Start-ot a rossztól. A felhasználó azt várja, hogy visszatérve az alkalmazásba ugyanazt lássa, amit elhagyott — beleértve a görgetési pozíciót, a mezők szövegét, a kiválasztott lapokat.

onSaveInstanceState

A rendszer az onSaveInstanceState-t hívja meg az Activity megsemmisítésekor, de MIELŐTT a folyamat megölhető. A Bundle-ben csak egyszerű adatok (String, Int, Parcelable, Serializable) kerülnek mentésre. Összetett adatokhoz használja a SavedStateHandle-t a ViewModel-ben — automatikusan elmenti és visszaállítja a mezőket Warm Start esetén. Az onSaveInstanceState-tól eltérően a SavedStateHandle akkor is működik, ha a folyamat túlélte a Warm Start-ot (a ViewModel nem semmisül meg). Példa: az EditText szövegéhez használja a SavedStateHandle.getLiveData(„text“) hívást — a szöveg automatikusan mentésre és visszaállításra kerül.

ViewModel és Warm Start

Ha Warm Start esetén a folyamat nem ölődött meg, a ViewModel a memóriában marad és az onCleared nem hívódik meg. Ez azt jelenti, hogy az előző munkamenetben betöltött összes adat azonnal elérhető. De ha a folyamat megölték (az eszköz 30 percnél tovább deep sleep állapotban volt), a ViewModel megsemmisül és a SavedStateHandle segítségével jön létre újra. A ViewModel helyes működéséhez Warm Start esetén használjon SavedStateHandle-t olyan mezőkkel, amelyeket bármilyen forgatókönyv esetén vissza kell állítani. Különbség: a @HiltViewModel annotációval ellátott ViewModel automatikusan támogatja a SavedStateHandle-t.

MechanizmusFolyamat élFolyamat megölt
ViewModelAdatok a memóriábanMegsemmisült, újra létrejön
SavedStateHandleAdatok a memóriábanVisszaáll a Bundle-ből
onSaveInstanceStateActivity kitöltésekor hívódikNem hívódik
Room DBGyorsítótár elérhetőGyorsítótár elérhető (lemez)

RecyclerView görgetési pozíciójának megőrzése

A Warm Start egyik leggyakoribb problémája — a görgetési pozíció elvesztése. A felhasználó az 50. elemig görgette a hírfolyamot, minimalizálta az alkalmazást, visszatért — és a lista elejét látja. Megoldás: mentse el a layoutManager.onSaveInstanceState-t (megőrzi az első látható elem pozícióját és offset-jét), és állítsa vissza az onRestoreInstanceState-ben. Az utolsó látható pozíciót elmentheti a SharedPreferences-ben dátum/idő kulccsal is, hogy Warm Start esetén gyorsan visszaállítsa a pozíciót.

kotlin
// RecyclerView görgetési pozíciójának mentése
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) }
}

Kódpéldák Warm Start-hoz

Két gyakorlati példa a Warm Start optimalizálására: a SavedStateHandle használata a ViewModel-ben és az összetett adatok aszinkron visszaállítása az indítás után.

ViewModel SavedStateHandle-lel

A SavedStateHandle automatikusan elmenti a mezőket a Bundle-ben és visszaállítja őket Warm Start esetén. A felhasználói profil mező (String, JSON) további szerverlekérdezések nélkül áll vissza. Ha a folyamatot megölték, a SavedStateHandle betölti az utolsó mentett állapotot a Bundle-ből.

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 nem null, UI loader nélkül
// Betöltés után: profile frissül a SavedStateHandle-ben

AsyncLayoutInflater nehéz képernyőhöz

Ha az első képernyő összetett elrendezést (térkép, gradients, több lista) tartalmaz, használja az AsyncLayoutInflater-t a nehéz elemek háttérben történő kiterjesztésére. Amíg az elrendezés kiterjesztésre kerül, jelenítsen meg egy placeholder-t shimmer effektussal. Ez különösen fontos Warm Start esetén, ahol minden ezredmásodperc számít. Az AsyncLayoutInflater háttérszálon dolgozik, és a kész View-t callback-en keresztül juttatja el a főszálra.

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

        // Placeholder elrendezés azonnali megjelenítéshez
        setContentView(R.layout.placeholder_shimmer)

        // Nehéz elrendezés aszinkron betöltése
        AsyncLayoutInflater(this).inflate(
            R.layout.activity_main_complex,
            findViewById(R.id.container)
        ) { view, resId, parent ->
            parent?.removeAllViews()
            parent?.addView(view)
        }
    }
}

Gyakran ismételt kérdések

Átalakulhat-e a Warm Start Cold Start-tá?

Igen, ha a Warm Start pillanatában a rendszer úgy dönt, hogy megöli az alkalmazás folyamatát (például memória felszabadítása céljából egy másik alkalmazás számára), az indítás nulláról Cold Start-tá válik. Ez 2–3 GB RAM-mal rendelkező eszközökön fordul elő, amikor több alkalmazás egyidejűleg fut. A gyakorlatban a Warm Start csak 10–20 percig garantált a minimalizálás után középkategóriás eszközökön.

Megmarad-e a ViewModel Warm Start esetén?

Igen, ha a folyamat nem ölődött meg, a ViewModel a memóriában marad és az onCleared nem hívódik meg. Ez a Warm Start kulcsfontosságú előnye: az összes betöltött adat, hálózati kérés, ViewModel-ben lévő gyorsítótár — azonnal elérhető. Ha a folyamatot megölték, a ViewModel a ViewModelProvider.Factory vagy @HiltViewModel segítségével jön létre újra, és a SavedStateHandle visszaállítja a mentett mezőket.

Miért lehet lassabb a Warm Start, mint a Cold Start?

Elméletileg a Warm Start mindig gyorsabb, mint a Cold Start, de a gyakorlatban vannak olyan forgatókönyvek, ahol a különbség minimális: ha az Application.onCreate könnyű (50 ms) és az Activity.onCreate nehéz (800 ms), akkor a Warm Start (800 ms) majdnem egyenlő a Cold Start-tal (850 ms). Ebben az esetben nem az Application-t, hanem az Activity.onCreate-t kell optimalizálni — ez válik a Warm Start szűk keresztmetszetévé.

Hogyan hat a SplashScreen API a Warm Start-ra?

Az Android 12+ rendszerben a SplashScreen API azonnal megjeleníti a rendszer splash-t (ikon színes háttérrel) az indításkor — mind Cold, mind Warm Start esetén. Warm Start esetén a splash csak 100–300 ms-ig látszik, majd az alkalmazás UI-ja váltja fel. A SplashScreen maga nem gyorsítja fel az indítást, de elrejti az Activity létrehozásának idejét, javítva az észlelést.

Kell-e optimalizálni a Warm Start-ot, ha a Cold Start már gyors?

Igen, mert a Warm Start 2–3-szor gyakrabban fordul elő, mint a Cold Start. Ha a Cold Start 1,2 másodpercig tart, a Warm Start pedig 600 ms, akkor az indítások 40%-a (Warm) még mindig 0,6 másodpercig tart, ami érezhető. A Warm Start 200–300 ms-ra optimalizálása azonnali visszatérés érzését adja a felhasználónak. A 6+ GB RAM-mal rendelkező eszközökön a Warm Start az összes indítás akár 80%-át is kiteheti, és optimalizálása prioritássá válik.

Összefoglalás

  • Warm Start — indítás meglévő folyamattal, Activity nélkül a memóriában, idő 200–800 ms
  • Fő különbség a Cold Start-tól: Application.onCreate nem fut le, osztályok betöltve
  • A Warm Start három fázisa: kezdő ablak → Activity létrehozása → első képkocka
  • ADB-n keresztül -S jelző nélkül vagy Macrobenchmark-kal StartupMode.WARM beállítással mérhető
  • Optimalizálás: SavedStateHandle, AsyncLayoutInflater, cache-then-network, ConstraintLayout
  • ViewModel megmarad Warm Start esetén (élő folyamat) — adatok azonnal elérhetők
  • Warm Start az összes alkalmazásindítás 40–80%-át teszi ki

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is