Warm Start: esența, pornirea la cald și optimizarea în Android

Autor: IT Sectr Publicat: 2026-03-31 Timp de citire: 8 min

Warm Start — este un scenariu de pornire a aplicației Android în care procesul aplicației există deja în memorie (de exemplu, după minimizare), dar Activity a fost distrusă de sistem pentru economisirea resurselor. Application.onCreate a fost deja executat, clasele sunt încărcate, dar UI este creat din nou. Conform Google, 2024, Warm Start durează între 200 și 800 ms și reprezintă aproximativ 40% din toate pornirile pe dispozitive cu 4 GB RAM.

Principalele

  • Warm Start — pornirea aplicației cu un proces existent, dar fără Activity în memorie
  • Diferența de Cold Start: Application.onCreate nu se execută, clasele sunt deja încărcate
  • Timpul Warm Start este de 200–800 ms față de 1–5 secunde pentru Cold Start
  • Scenarii: revenirea la aplicație după câteva ore, eliberarea Activity de OOM-killer
  • Optimizarea se concentrează pe păstrarea stării Activity și memorarea în cache a datelor

Ce este Warm Start

Warm Start (pornire la cald) — este o stare între Cold Start și Hot Start: procesul aplicației există în memorie (uneori în memoria cache de fundal a Linux), dar Activity nu este activă și va fi creată din nou. Sistemul Android, atunci când memoria RAM este insuficientă, poate elibera Activity din stivă, lăsând procesul în viață. Când utilizatorul revine la aplicație, pornește Warm Start: se creează o nouă instanță Activity, se execută metodele ciclului de viață onCreate → onStart → onResume, dar Application.onCreate și încărcarea claselor sunt omise.

Cauzele Warm Start

Sistemul Android ia decizia de a elibera Activity pe baza priorității procesului (importance rank). Activity în fundal (nivel PROCESS_STATE_IMPORTANT_FOREGROUND sau PROCESS_STATE_TOP_SLEEPING) poate fi distrusă după 5–30 de minute de la minimizarea aplicației, în funcție de RAM-ul disponibil. Pe dispozitivele cu 3 GB RAM, Activity poate fi eliberată după doar 10 minute, pe dispozitivele cu 8 GB — după câteva ore. Important: la Warm Start, onSaveInstanceState este apelat înainte de distrugerea Activity, iar dezvoltatorul poate salva starea UI.

Percepția utilizatorului

Utilizatorul nu vede diferența între Warm și Cold Start — el doar apasă pe iconița aplicației și așteaptă. Totuși, la Warm Start, ecranul alb (blank window) poate apărea dacă aplicația nu și-a configurat propria temă pentru fereastra de pornire. Google recomandă setarea unei teme personalizate în manifest (Theme.AppCompat.Light sau Theme.Material3.DayNight) pentru Activity de pornire, pentru a evita pâlpâirea ecranului alb/negru la Warm Start. Pe Android 12+, SplashScreen API ascunde de asemenea acest efect.

Warm Start vs Cold Start vs Hot Start

Înțelegerea diferenței dintre cele trei tipuri de pornire este necesară pentru alegerea strategiei corecte de profilare și optimizare. Fiecare tip are propria durată, propriile blocaje și propriile instrumente de măsurare.

CriteriuCold StartWarm StartHot Start
ProcesCreat din nouExistă în memorieExistă în memorie
Application.onCreateSe executăNu se executăNu se execută
ActivityCreată de la zeroCreată de la zeroRestaurată din stivă
Timp1–5 secunde200–800 ms< 200 ms
onCreate ActivityCompletComplet (cu restaurare)Omis

În practică, Warm Start constituie de la 30% la 60% din toate pornirile aplicației, în funcție de obiceiurile utilizatorului și cantitatea de RAM a dispozitivului. Utilizatorii care țin multe aplicații deschise (multitasker) se confruntă mai des cu Warm Start. Pentru rețelele sociale și mesagerie, Warm Start este cel mai frecvent scenariu, deoarece aplicația este tot timpul în fundal. Pentru aplicațiile bancare, dimpotrivă, predomină Cold Start (îpărtarea forțată a procesului din motive de securitate).

Fazele pornirii la cald

Warm Start constă din trei faze, fiecare dintre ele putând fi măsurată și optimizată. Spre deosebire de Cold Start, aici nu există faza de fork și încărcare a claselor, dar există o fază de restaurare a stării (restore) care poate fi costisitoare.

Faza 1: Fereastra de pornire (window background)

Sistemul verifică dacă aplicația are o temă pentru fereastra de pornire. Dacă tema nu este setată, se afișează un ecran alb (sau negru, în funcție de sistem). Dacă tema este setată, se afișează fundalul din temă. Această fază durează 10–30 ms, dar este vizibilă dacă tema nu se potrivește cu UI-ul real al aplicației. Folosiți Theme.Material3.DayNight cu un windowBackground personalizat a cărui culoare coincide cu fundalul primului ecran — aceasta creează un efect de încărcare instantanee.

Faza 2: Crearea Activity (restore)

Sistemul apelează onCreate cu transmiterea Bundle savedInstanceState care a fost salvat în onSaveInstanceState înainte de distrugerea Activity. Dacă aplicația a salvat corect starea (textul câmpurilor, poziția de derulare, datele ViewModel), restaurarea are loc rapid. În caz contrar — Activity începe de la o pagină curată, iar utilizatorul vede un loader până când datele se încarcă. Momentul cheie: obiectele ViewModel supraviețuiesc Warm Start doar dacă procesul nu a fost distrus — la Warm Start, ViewModel rămâne în memorie.

Faza 3: Primul cadru (TTFD)

După onCreate se execută onStart → onResume, iar sistemul apelează primul randament. TTFD (Time To First Draw) pentru Warm Start trebuie să fie sub 300 ms pe un dispozitiv mediu. Dacă primul ecran conține un RecyclerView complex cu View-uri grele sau încarcă imagini din rețea, TTFD poate depăși pragul. Folosiți Placeholder și Shimmer pentru încărcarea lină a conținutului după primul cadru.

Cum să măsurăm Warm Start

Măsurarea Warm Start este mai dificilă decât Cold Start, deoarece trebuie să simulați starea „proces viu, Activity distrusă”. Comanda standard ADB cu flag-ul -S nu este potrivită — omoară procesul. Pentru Warm Start, folosiți alte abordări.

ADB shell am start fără -S

Mai întâi, porniți aplicația prin adb shell monkey sau atingând iconița, apoi minimizați-o (adb shell input keyevent 3 keyevent HOME). Așteptați 5–10 secunde pentru ca sistemul să poată elibera Activity și lansați adb shell am start -W (fără -S). Comanda va returna timpul de pornire, care va fi mai scurt decât Cold Start. Pentru reproductibilitate, folosiți un script: pornire → așteptare → home → așteptare → pornire.

bash
# Simularea Warm Start prin ADB
$ adb shell am start -W \
    com.example.app/.MainActivity

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

Macrobenchmark pentru Warm Start

Biblioteca androidx.benchmark.macro suportă măsurarea Warm Start. Pentru aceasta, în test setați startupMode = StartupMode.WARM — biblioteca va porni aplicația, o va minimiza, va aștepta (configurable delay) și apoi va măsura repornirea. Macrobenchmark face 10–20 de rulări și calculează percentilii. În CI/CD puteți seta un prag: dacă P50 Warm Start depășește 600 ms — testul eșuează. Aceasta permite urmărirea regresiunilor la fiecare commit.

Firebase Performance Monitoring

Firebase face automat distincția între Cold și Warm Start pe baza timpului de la închiderea anterioară a aplicației. Dacă aplicația a fost deschisă în ultimele 30 de minute, Firebase clasifică pornirea ca Warm. În consola Firebase veți vedea grafice separate pentru fiecare tip de pornire, ceea ce permite evaluarea eficienței optimizărilor. De exemplu, după implementarea salvării stării în ViewModel, se poate observa o reducere de 30% a Warm Start.

Cum să optimizăm Warm Start

Optimizarea Warm Start se concentrează pe două direcții: accelerarea Activity.onCreate și restaurarea corectă a stării. Deoarece Application.onCreate și încărcarea claselor sunt deja executate, blocajul principal este codul UI al primului ecran.

Restaurarea asincronă a stării

Dacă starea salvată (savedInstanceState) conține date care trebuie deserializate (Bitmap, String, JSON), faceți acest lucru în firul de fundal. În loc să citiți direct din Bundle în onCreate, lansați o corutină și afișați un ecran shimmer. În practică, deserializarea Bundle pe un dispozitiv mediu durează 20–100 ms — pare puțin, dar pentru Warm Start aceasta reprezintă 10–50% din timpul total. Folosiți Saved State Module al bibliotecii Jetpack, care salvează și restaurează automat starea ViewModel în Bundle sau baza de date.

Optimizarea setContentView

Expandarea layout-ului XML (layout inflation) — una dintre cele mai costisitoare etape ale Warm Start. Dacă primul ecran folosește un CoordinatorLayout complex cu AppBar, CollapsingToolbar, NestedScrollView plus trei RecyclerView, timpul de inflation poate atinge 300 ms. Soluții: folosiți ConstraintLayout pentru o ierarhie plată, aplicați ViewStub pentru secțiunile invizibile la pornire (bottom sheet, dialog), activați expandarea asincronă pentru fragmentele grele prin AsyncLayoutInflater. În Jetpack Compose, inflation nu este necesar, dar compilarea arborelui Compose la Warm Start poate dura un timp similar.

Memorarea în cache a datelor

La Warm Start, datele pe care aplicația le-a încărcat în sesiunea anterioară pot fi deja în cache: baza de date Room, SharedPreferences, memoria cache in-memory în ViewModel. Dacă primul ecran afișează o listă de pe server, verificați cache-ul la pornire și actualizați datele în fundal. Folosiți strategia cache-then-network: mai întâi afișați datele din cache (instantaneu), apoi actualizați de pe server (asincron). Aceasta reduce timpul perceput al Warm Start la 100–200 ms.

kotlin
// ViewModel cu memorare în cache pentru Warm Start
class FeedViewModel : ViewModel() {
    private val cache = MutableStateFlow<List<Item>>(emptyList())

    init {
        // Mai întâi cache, apoi rețeaua
        viewModelScope.launch {
            cache.emit(db.getItems()) // Warm Start: datele sunt deja în baza de date
            cache.emit(api.fetchItems()) // Actualizare în fundal
        }
    }
}

Păstrarea stării la Warm Start

Salvarea corectă a stării — factorul cheie care diferențiază un Warm Start bun de unul prost. Utilizatorul se așteaptă să revină în aplicație și să vadă același lucru pe care l-a lăsat — inclusiv poziția de derulare, textul în câmpuri, filele selectate.

onSaveInstanceState

Sistemul apelează onSaveInstanceState la distrugerea Activity, dar ÎNAINTE ca procesul să poată fi ucis. În Bundle se salvează doar date simple (String, Int, Parcelable, Serializable). Pentru date complexe, folosiți SavedStateHandle în ViewModel — acesta salvează și restaurează automat câmpurile la Warm Start. Spre deosebire de onSaveInstanceState, SavedStateHandle funcționează chiar dacă procesul a supraviețuit Warm Start (ViewModel nu este distrus). Exemplu: pentru textul în EditText, folosiți SavedStateHandle.getLiveData(“text”) — textul se va salva și restaura automat.

ViewModel și Warm Start

Dacă la Warm Start procesul nu a fost ucis, ViewModel rămâne în memorie și onCleared nu este apelat. Aceasta înseamnă că toate datele încărcate în sesiunea anterioară sunt disponibile instantaneu. Totuși, dacă procesul a fost ucis (dispozitivul în deep sleep mai mult de 30 de minute), ViewModel este distrus și creat din nou cu SavedStateHandle. Pentru funcționarea corectă a ViewModel la Warm Start, folosiți SavedStateHandle cu câmpuri care trebuie restaurate în orice scenariu. Diferența: ViewModel cu @HiltViewModel suportă SavedStateHandle automat.

MecanismProces viuProces ucis
ViewModelDate în memorieDistrus, creat din nou
SavedStateHandleDate în memorieRestaurate din Bundle
onSaveInstanceStateApelat la eliberarea ActivityNu este apelat
Room DBCache disponibilCache disponibil (disc)

Salvarea derulării RecyclerView

Una dintre cele mai frecvente probleme ale Warm Start — pierderea poziției de derulare. Utilizatorul derula lista până la al 50-lea element, a minimizat aplicația, s-a întors — și vede începutul listei. Soluția: salvați layoutManager.onSaveInstanceState (salvează poziția și offset-ul primului element vizibil) și restaurați-l în onRestoreInstanceState. De asemenea, puteți salva ultima poziție vizibilă în SharedPreferences cu o cheie după dată/oră pentru a restaura rapid poziția la Warm Start.

kotlin
// Salvarea poziției de derulare RecyclerView
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) }
}

Exemple de cod pentru Warm Start

Două exemple practice de optimizare a Warm Start: utilizarea SavedStateHandle în ViewModel și restaurarea asincronă a datelor complexe după pornire.

ViewModel cu SavedStateHandle

SavedStateHandle salvează automat câmpurile în Bundle și le restaurează la Warm Start. Câmpul de profil al utilizatorului (String, JSON) va fi restaurat fără cereri suplimentare la server. Dacă procesul a fost ucis, SavedStateHandle va încărca ultima stare salvată din 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: profilul nu este null, UI fără loader
// După încărcare: profilul se actualizează în SavedStateHandle

AsyncLayoutInflater pentru ecranul greu

Dacă primul ecran conține un layout complex (hartă, gradient, mai multe liste), folosiți AsyncLayoutInflater pentru expandarea elementelor grele în fundal. În timp ce layout-ul se expandează, afișați un placeholder cu efect shimmer. Acest lucru este deosebit de important pentru Warm Start, unde fiecare milisecundă contează. AsyncLayoutInflater funcționează pe firul de fundal și transmite View-ul gata în callback pe firul principal.

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

        // Mockup Placeholder pentru randare instantanee
        setContentView(R.layout.placeholder_shimmer)

        // Încărcarea asincronă a layout-ului greu
        AsyncLayoutInflater(this).inflate(
            R.layout.activity_main_complex,
            findViewById(R.id.container)
        ) { view, resId, parent ->
            parent?.removeAllViews()
            parent?.addView(view)
        }
    }
}

Întrebări frecvente

Poate Warm Start să treacă în Cold Start?

Da, dacă în momentul Warm Start sistemul decide să ucidă procesul aplicației (de exemplu, pentru a elibera memoria pentru o altă aplicație), pornirea va deveni Cold Start de la zero. Aceasta se întâmplă pe dispozitivele cu 2–3 GB RAM la lucrul simultan al mai multor aplicații. Practic, Warm Start este garantat doar în decurs de 10–20 de minute după minimizare pe dispozitivele de clasă medie.

Se păstrează ViewModel la Warm Start?

Da, dacă procesul nu a fost ucis, ViewModel rămâne în memorie și onCleared nu este apelat. Acesta este avantajul cheie al Warm Start: toate datele încărcate, cererile de rețea, memoria cache în ViewModel — sunt disponibile instantaneu. Dacă procesul a fost ucis, ViewModel este creat din nou prin ViewModelProvider.Factory sau @HiltViewModel, iar SavedStateHandle restaurează câmpurile salvate.

De ce Warm Start poate fi mai lent decât Cold Start?

Teoretic, Warm Start este întotdeauna mai rapid decât Cold Start, dar în practică există scenarii când diferența este minimă: dacă Application.onCreate a fost ușor (50 ms), iar Activity.onCreate — greu (800 ms), atunci Warm Start (800 ms) este aproape egal cu Cold Start (850 ms). În acest caz, trebuie optimizat nu Application, ci Activity.onCreate — tocmai el devine blocajul pentru Warm Start.

Cum afectează SplashScreen API Warm Start?

SplashScreen API pe Android 12+ afișează un splash de sistem (iconiță pe fundal colorat) imediat la pornire — atât pentru Cold, cât și pentru Warm Start. Pentru Warm Start, splash-ul se afișează doar 100–300 ms, după care este înlocuit de UI-ul aplicației. SplashScreen nu accelerează pornirea în sine, dar maschează timpul de creare a Activity, îmbunătățind percepția.

Trebuie să optimizăm Warm Start dacă Cold Start este deja rapid?

Da, deoarece Warm Start apare de 2–3 ori mai des decât Cold Start. Dacă Cold Start durează 1.2 secunde, iar Warm Start — 600 ms, atunci 40% din porniri (Warm) încă durează 0.6 secunde, ceea ce este sesizabil. Optimizarea Warm Start la 200–300 ms oferă utilizatorului senzația de revenire instantanee. Pe dispozitivele cu 6+ GB RAM, Warm Start poate constitui până la 80% din toate pornirile, iar optimizarea sa devine prioritară.

Rezumat

  • Warm Start — pornirea aplicației cu un proces existent, fără Activity în memorie, timp 200–800 ms
  • Diferența principală de Cold Start: Application.onCreate nu se execută, clasele sunt încărcate
  • Trei faze ale Warm Start: fereastra de pornire → crearea Activity → primul cadru
  • Se măsoară prin ADB fără flag-ul -S sau Macrobenchmark cu StartupMode.WARM
  • Optimizare: SavedStateHandle, AsyncLayoutInflater, cache-then-network, ConstraintLayout
  • ViewModel se păstrează la Warm Start (proces viu) — date disponibile instantaneu
  • Warm Start constituie 40–80% din toate pornirile aplicației

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și