Jetpack Compose: baze, funcții Composable și State

Autor: IT Sectr Publicat: 2026-02-21 Timp de citire: 8 min

Jetpack Compose — framework-ul UI declarativ modern de la Google pentru dezvoltarea Android, lansat în versiunea stabilă 1.0 în iulie 2021. Compose înlocuiește marcarea XML imperativă și sistemul View cu funcții Kotlin cu adnotarea @Composable. Conform Google I/O (2025), Compose este folosit în 55% din proiectele noi pe Android, iar dimensiunea medie a codului UI se reduce cu 30–50% față de XML. Framework-ul redesenează automat doar părțile modificate ale ecranului la schimbarea State, eliminând apelarea manuală a notifyDataSetChanged sau findViewById.

Principal

  • Jetpack Compose — framework-ul UI declarativ Google pentru Android în Kotlin (funcții @Composable în loc de marcare XML).
  • @Composable — adnotarea funcției care descrie o parte a UI, poate accepta parametri și citi State.
  • State și MutableState — mecanism de reactivitate: la modificarea State, Compose repornește (recompose) doar funcțiile Composable dependente.
  • remember — funcția de cache a valorii între recompoziții; fără ea, State se resetează la fiecare actualizare.
  • Modifier — lanț de setări (padding, size, clickable, background) care gestionează aspectul și comportamentul Composable.

Ce este Jetpack Compose?

Jetpack Compose — framework-ul UI Google construit pe principii de programare reactivă. În loc de Activity cu layout-uri XML, FragmentManager și ViewBinding, dezvoltatorul descrie interfața prin funcții Kotlin cu adnotarea @Composable. Compose nu folosește LayoutInflater — UI este format din funcții Kotlin pure, compilate în bytecode. Framework-ul constă din mai multe biblioteci: Compose UI (componente de bază Text, Button, Column, Row), Compose Foundation (Material Design, Gesturi, Focus), Compose Material3 (Material You cu Dynamic Colors) și Compose Runtime (State, Side Effects, Coroutines). Compose funcționează pe Android API 21+ (Android 5.0) și este complet compatibil cu codul existent pe View/XML prin ComposeView — adaptorul AndroidView.

Compose vs View System

View System (2008) utilizează o ierarhie de obiecte View cu gestionare manuală: dezvoltatorul creează un layout XML, găsește View prin findViewById, implementează Adapter pentru RecyclerView și apelează notifyDataSetChanged la modificarea datelor. Compose descrie UI funcțional: la modificarea stării, framework-ul repornește (recompose) doar funcțiile Composable modificate, calculează diff și aplică modificări minime la Canvas. Performanța Compose este comparabilă cu View System, iar în scenarii cu liste complexe (LazyColumn) deseori depășește RecyclerView prin omiterea elementelor inutile prin parametrul key. În IT Sectr, Compose este folosit pentru modulele noi ale aplicațiilor Android cu minSdk 24+.

Funcții Composable: blocuri de construcție UI

@Composable — adnotarea care transformă o funcție obișnuită Kotlin într-un bloc de construcție UI. Funcțiile Composable pot apela alte funcții Composable, formând un arbore de componente. Spre deosebire de View, funcțiile Composable nu au stare implicit — sunt stateless și se redesenează la fiecare modificare a parametrilor de intrare sau a State. Compilatorul (Compose Compiler) transformă funcțiile @Composable în cod care poate fi întrerupt și reluat (positional memoization) — acest lucru permite lui Compose să repornească doar părțile modificate fără reconstruirea completă a arborelui.

kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun UserProfile(name: String, avatarUrl: String) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        AsyncImage(
            model = avatarUrl,
            contentDescription = "User avatar",
            modifier = Modifier.size(48.dp)
        )
        Spacer(modifier = Modifier.width(12.dp))
        Text(
            text = name,
            style = MaterialTheme.typography.titleMedium
        )
    }
}

Funcția UserProfile primește name și avatarUrl ca parametri, construiește un rând cu avatar și nume. Modifier.fillMaxWidth() întinde componentul pe toată lățimea, .padding(16.dp) adaugă margini. MaterialTheme.typography.titleMedium folosește stilul de sistem Material 3. La modificarea parametrilor name sau avatarUrl, Compose repornește UserProfile — recrearea componentului cu noile valori.

State și Recomposition în Jetpack Compose

State în Compose — orice valoare a cărei modificare cauzează recompoziția (repornirea) funcțiilor @Composable dependente. Metoda de bază este mutableStateOf(), care creează MutableState<T> cu suport pentru sistemul de snapshot-uri Compose. Snapshot — mecanism de urmărire a modificărilor: la scrierea în State, Compose marchează Snapshot-ul curent ca dirty, iar planificatorul de recompoziție repornește doar funcțiile Composable care citesc acest State. Pentru colecții observabile utilizați mutableStateListOf() și mutableStateMapOf(). Compose suportă State din componente Lifecycle-Aware prin collectAsState() pentru Kotlin Flow și observeAsState() pentru LiveData.

kotlin
@Composable
fun LikeButton() {
    var liked by remember { mutableStateOf(false) }
    var count by remember { mutableStateOf(42) }
    
    Button(
        onClick = {
            liked = !liked
            if (liked) count++ else count--
        },
        colors = ButtonDefaults.buttonColors(
            containerColor = if (liked) MaterialTheme.colorScheme.primary
                else MaterialTheme.colorScheme.surfaceVariant
        )
    ) {
        Text("♥ $count")
    }
}

Codul creează un buton «Like» cu starea liked (Boolean) și count (Int), stocate prin mutableStateOf(). La apăsare, liked este inversat, contorul crește/scade — Compose repornește automat LikeButton. by delegate permite utilizarea State ca o variabilă obișnuită: liked = !liked în loc de liked.value = !liked.value. Culoarea butonului se schimbă reactiv între primary (apreciat) și surfaceVariant (neapreciat).

remember: cache între recompoziții

remember — funcția Compose care stochează în cache valoarea între recompoziții. Fără remember, fiecare repornire a funcției Composable creează o stare nouă (mutableStateOf) — acest lucru strică logica aplicației: la rotirea ecranului sau modificarea State-ului părinte, contorul se resetează. remember primește o lambda-calculator și calculează valoarea doar la prima compoziție; la următoarele returnează rezultatul stocat în cache. Pentru resetarea cache-ului utilizați remember(key) — cheia determină când să recalculeze valoarea. remember(key1, key2) recalculează la modificarea oricărei chei. Pentru stări de lungă durată (care supraviețuiesc rotirii ecranului) utilizați rememberSaveable — analogul remember cu salvare în Bundle prin SavedStateHandle.

kotlin
@Composable
fun TimerScreen() {
    var seconds by rememberSaveable { mutableStateOf(0) }
    
    LaunchedEffect(Unit) {
        while (true) {
            delay(1000)
            seconds++
        }
    }
    
    Column(
        modifier = Modifier.fillMaxSize().padding(32.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            text = "Timp scurs: ${seconds}s",
            style = MaterialTheme.typography.displayMedium
        )
    }
}

rememberSaveable păstrează seconds la rotirea ecranului (modificare de configurare). LaunchedEffect pornește o corutină care incrementează seconds în fiecare secundă. La recompoziția TimerScreen (în fiecare secundă) seconds nu se resetează datorită lui rememberSaveable. Utilizați remember obișnuit pentru starea care nu ar trebui să supraviețuiască modificărilor de configurare (de exemplu, flag-uri de animație).

Modifier: lanț de setări Composable

Modifier — obiect-container imutabil care implementează pattern-ul Builder pentru setarea aspectului, comportamentului și layout-ului componentelor Composable. Fiecare apel al metodei Modifier (.padding(), .width(), .clickable(), .background()) returnează un nou Modifier cu elementul adăugat. Ordinea modificatorilor contează: .padding(16.dp).clickable { } — marginea se aplică înaintea handler-ului de click, clickable urmărește întreaga zonă ținând cont de margine. .clickable { }.padding(16.dp) — întreaga zonă înainte de margine este clickabilă, marginea deplasează conținutul în interior. Modifier suportă implementări personalizate prin then(otherModifier) și compositionLocal pentru acces la setările părinte.

kotlin
@Composable
fun CardExample() {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
            .clickable { println("Card apăsat") },
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surfaceVariant
        )
    ) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text("Jetpack Compose", style = MaterialTheme.typography.titleLarge)
            Spacer(modifier = Modifier.height(8.dp))
            Text(
                "UI declarativ pentru Android cu State și Modifier",
                style = MaterialTheme.typography.bodyMedium
            )
        }
    }
}

CardExample demonstrează lanțul Modifier: fillMaxWidth + padding + clickable. Card — component Material3 cu propriile setări elevation și colors. Column-ul imbricat are un padding intern de 16dp. Compose Material3 ajustează automat culorile la Dynamic Color (Material You) pe Android 12+. Card este unul dintre cele 30+ componente Material3 încorporate în Compose.

State hoisting și arhitectura Compose

State hoisting — pattern-ul de ridicare a stării din funcția Composable în apelantul său, făcând funcția stateless. Componentul stateless primește date și callback-uri prin parametri, neavând propriul State. Aceasta crește reutilizabilitatea și testabilitatea: componentul poate fi apelat cu diferite State și testat în preview. Google recomandă arhitectura: ViewModel + StateFlow (sau MutableStateFlow) + collectAsState() în Compose. ViewModel ridică starea la nivelul ecranului, Compose afișează. Efectele secundare (LaunchedEffect, DisposableEffect) gestionează evenimentele unice.

ComponentResponsabilitateTehnologie
ViewModelStocare State, logică de businessStateFlow, MutableStateFlow
Screen ComposableOrganizarea ecranului, State hoistingcollectAsState(), Scaffold, LazyColumn
Stateless ComponentUI fără stare, afișare pură@Composable parametri + lambde
Side EffectAcțiuni unice (snackbar, navigare)LaunchedEffect, SnackbarHostState

Întrebări frecvente

Cu ce se deosebește Jetpack Compose de layout-urile XML?

Layout-urile XML sunt imperative: LayoutInflater încarcă XML, findViewById găsește View, dezvoltatorul actualizează manual textul/listele. Compose este declarativ: UI se descrie prin funcții Kotlin @Composable, iar framework-ul redesenează automat doar părțile modificate la schimbarea State. Compose reduce volumul codului UI cu 30–50% și nu folosește XML.

Este necesară o bibliotecă separată pentru navigare în Compose?

Da, Google oferă Navigation Compose — o bibliotecă pentru navigare declarativă între ecrane. NavController gestionează stiva de rute, composable() înregistrează ecranele, navArgument transmite parametri. Alternative: Voyager (comunitate) și Decompose (Badoo). Navigation Compose este standardul oficial cu suport pentru deep links și argumente type-safe.

Ce este Modifier în Jetpack Compose?

Modifier — un container imutabil de pattern-uri de styling (padding, size, clickable, background, border, clip) aplicate componentelor Composable. Fiecare apel returnează un nou Modifier cu elementul adăugat. Ordinea contează: .padding().clickable() aplică marginea înainte de click, .clickable().padding() — invers. Modifier este modul principal de personalizare a componentelor Compose.

Funcționează Compose pe toate versiunile Android?

Jetpack Compose suportă Android API 21+ (Android 5.0 Lollipop) prin Compose Compiler și Compose BOM. Material 3 (Dynamic Colors) este disponibil pe Android 12+; pe versiunile mai vechi se folosește o paletă de rezervă. Pentru proiecte noi, Apple recomandă minSdk 24+ (Android 7.0), ceea ce este acoperit complet de Compose.

Cum se testează componentele Compose?

Google oferă Compose UI Test — o bibliotecă pentru testare pe JVM (Desktop) și emulator. Funcții principale: composeTestRule.setContent { } pentru randarea componentului, onNodeWithText() pentru căutarea elementelor, performClick()/performTextInput() pentru acțiuni. Testele Espresso sunt compatibile cu Compose prin ComposeTestRule, dar Compose UI Test este abordarea preferată și mai rapidă.

Concluzii

  • Jetpack Compose — framework-ul UI declarativ Google pentru Android cu funcții Kotlin @Composable în loc de XML (stabil din 2021).
  • @Composable — adnotarea care transformă o funcție Kotlin într-un component UI; arborele de funcții Composable înlocuiește ierarhia View.
  • State și mutableStateOf — baza reactivității Compose prin sistemul Snapshot; recompoziția afectează doar funcțiile dependente.
  • remember stochează în cache valoarea între recompoziții; rememberSaveable păstrează State la modificări de configurare.
  • Modifier — lanț de setări (padding, size, clickable, background) care formează un container imutabil; ordinea modificatorilor contează.
  • State hoisting — pattern-ul de ridicare a stării pentru componente stateless; ViewModel + StateFlow + collectAsState() — arhitectura recomandată.
  • Material 3 cu Dynamic Colors (Android 12+) — tema standard Compose cu adaptare automată la tapetul dispozitivului.

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