Jetpack Compuse este un set modern declarativ de instrumente pentru construirea interfețelor Android în Kotlin. Dezvoltatorul descrie UI prin funcții composable, iar setul de instrumente redesenează automat doar părțile modificate. Conform Android Developers (2026), Jetpack Compose funcționează pe Android 5.0 (API 21) și superior, suportă Material Design 3 și atinge 120 FPS pe dispozitive de gamă medie datorită propriului sistem Recomposition — un algoritm inteligent diff care actualizează doar widget-urile modificate.
Principalele puncte
Jetpack Compose — este un framework declarativ de la Google pentru construirea interfețelor de utilizator Android, anunțat în 2019 și care a atins o versiune stabilă în 2021. Spre deosebire de vechiul View System (XML + Activity/Fragment), Compose utilizează funcții Kotlin adnotate — @Composable. Interfața este descrisă integral în Kotlin: nu există separare între XML și cod. Aceasta a eliminat clasa de erori legate de nepotrivirea id-urilor în XML și Kotlin (type-safe synthetic nu ajuta la refactorizare).
Compose este construit pe propriul sistem de randare — Canvas, nelegat de ierarhia View. Fiecare Composable desenează direct pe Canvas, ocolind onMeasure/onDraw al View System. Aceasta oferă un câștig de performanță pe ecrane complexe: în testele Google (2023), un ecran Compose cu 200 de elemente s-a randat cu 40% mai rapid decât unul analog pe RecyclerView + ViewHolder.
Pentru funcționare, Compose necesită minSdk 21 (Android 5.0) și Kotlin 1.9+. Compose BOM (Bill of Materials) sincronizează versiunile tuturor bibliotecilor Compose. Framework-ul este compatibil cu codul existent pe View System: Compose se încorporează prin ComposeView în XML, iar View-urile vechi prin AndroidView în ierarhia Compose. Conform datelor Google Play Console (2025), Android 5.0+ acoperă 97% din dispozitivele active, astfel că compatibilitatea nu este o limitare pentru majoritatea proiectelor.
@Composable — este o adnotare care transformă o funcție obișnuită Kotlin într-un bloc de construcție UI. Funcția Composable descrie cum ar trebui să arate un fragment de interfață — text, buton, listă. În loc să returneze o valoare, funcția emite componente UI în compoziție. Aceasta seamănă cu un generator: fiecare funcție adaugă elemente pe ecran la apelare.
@Composable
fun ProfileCard(name: String, avatarUrl: String) {
Card(
modifier = Modifier.fillMaxWidth().padding(16.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surface
)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
AsyncImage(
model = avatarUrl,
contentDescription = "Avatar",
modifier = Modifier.size(48.dp).clip(CircleShape)
)
Spacer(Modifier.width(12.dp))
Text(
text = name,
style = MaterialTheme.typography.titleMedium
)
}
}
}
Funcția ProfileCard primește parametri (name, avatarUrl) și emite Card → Row → AsyncImage + Text. Compoziția — este un arbore de componente emise într-o singură trecere. Dacă parametrii nu s-au modificat, Compose omite apelul funcției (recomposition skip). Dacă s-a modificat doar name, va fi apelat doar Text, celelalte elemente nu vor fi redesenate. O astfel de intelligent recomposition — este avantajul cheie de performanță al Compose față de optimizarea manuală a View System.
Funcțiile Composable utilizează activ sloturi — trailing lambda, content: @Composable (() -> Unit). Aceasta permite crearea containerelor: Card, Column, Row primesc lambda content, iar conținutul se încorporează în locul slotului. Slot API a înlocuit atributele XML de tip android:layout_gravity — acum poziționarea elementelor copil se stabilește prin cod Kotlin în interiorul blocului content.
Starea în Compose — este orice valoare care se poate modifica în timp. Când starea se modifică, Compose planifică recomposition pentru toate componentele care citesc această stare. Mecanismul amintește de React hooks: mutableStateOf returnează MutableState, citirea .value abonează automat compoziția curentă la modificări.
@Composable
fun CounterExample() {
var count by remember { mutableStateOf(0) }
Column(modifier = Modifier.padding(16.dp)) {
Text("Apăsat: $count")
Button(onClick = { count++ }) {
Text("Mărește")
}
}
}
@Composable
fun UserScreen(viewModel: UserViewModel) {
val userName by viewModel.userName.collectAsState()
Text("Utilizator: $userName")
}
remember păstrează valoarea între recompoziții — altfel mutableStateOf ar fi creat din nou la fiecare actualizare UI. collectAsState() convertește StateFlow din ViewModel într-o stare compatibilă cu Compose. Recomandare — pentru starea ecranului utilizați ViewModel cu StateFlow, pentru starea locală (de exemplu, card extins) — mutableStateOf. Această separare corespunde principiului componentelor „inteligente/proaste".
State Hoisting — este un model de extragere a stării din componenta copil în componenta părinte. Părintele transmite valoarea și callback-ul prin parametri, copilul apelează callback-ul la modificare. Părintele stochează mutableStateOf, copilul — doar parametrii. Aceasta face componenta reutilizabilă și testabilă: același TextField poate fi utilizat cu orice sursă de date.
Modifier — este un obiect care descrie transformările Composable: dimensiune, spațieri, fundal, procesarea clicurilor, animația, derularea. Modificatorii se aplică printr-un lanț de apeluri: Modifier.fillMaxWidth().padding(16.dp).background(Color.Blue).clickable { }. Fiecare apel returnează un nou Modifier cu proprietatea adăugată — fără mutarea obiectului original.
Ordinea modificatorilor este importantă. Modifier.padding(16.dp).background(Color.Blue) colorează zona cu spațiere. Modifier.background(Color.Blue).padding(16.dp) colorează dreptunghiul interior, iar spațierea rămâne transparentă. Mecanica seamănă cu modelul CSS box: padding → background funcționează ca margin + background; background → padding — ca background + padding în interior. Dezvoltatorul trebuie să rețină: padding mai întâi = spațiere externă, padding după = internă.
Dacă modificatorii încorporați nu sunt suficienți, se creează unul personalizat prin Modifier.composed { ... } sau Modifier.then(). În interiorul modificatorului personalizat pot fi utilizate măsurători de layout (Modifier.layout { measurable, constraints -> ... }), desenare (Modifier.drawWithContent { ... }), gesturi (Modifier.pointerInput { ... }). Exemplu: modificator pentru animație pulsantă la apăsare — măsoară dimensiunea, la clic pornește animația de scalare prin animateFloatAsState.
Pentru animații, Compuse oferă animate*AsState (animateFloatAsState, animateColorAsState, animateDpAsState) — valorile se animează între starea veche și cea nouă la modificare. Dacă este necesară animația apariției/dispariției — AnimatedVisibility și AnimatedContent cu tranziții încorporate (fade, slide, expand). Toate animațiile funcționează pe graphics layer, fără a provoca compoziție suplimentară.
Funcțiile Composable nu ar trebui să execute acțiuni secundare direct (cereri de rețea, temporizatoare, abonamente) — ele sunt apelate la fiecare recompoziție, ceea ce ar duce la duplicarea cererilor. Pentru efecte secundare, Compose oferă familia de funcții Effect: LaunchedEffect pornește o corutină la intrarea în compoziție și o anulează la ieșire, DisposableEffect — pentru resurse care necesită curățare explicită (senzori, BroadcastReceiver).
@Composable
fun SensorReader() {
val context = LocalContext.current
var sensorValue by remember { mutableStateOf(0f) }
DisposableEffect(Unit) {
val sensor = registerSensorListener(context) { value ->
sensorValue = value
}
onDispose {
unregisterSensorListener(sensor)
}
}
Text("Valoare: $sensorValue")
}
@Composable
fun UserGreeting(userId: String) {
LaunchedEffect(userId) {
val profile = api.fetchProfile(userId)
// actualizare stare
}
}
LaunchedEffect(userId) se repornește dacă userId s-a modificat — corutina anterioară este anulată, una nouă pornește cu noul userId. Aceasta elimină gestionarea manuală a anulării cererilor. DisposableEffect(Unit) — efect cu cheia fixă Unit, se declanșează la intrarea în compoziție și apelează onDispose la ieșire. SensorReader înregistrează un ascultător și se dezabonează la părăsirea ecranului — fără risc de scurgere de memorie.
Dacă corutina trebuie pornită nu la intrarea în compoziție, ci la un eveniment (apăsarea unui buton), se utilizează rememberCoroutineScope(). Acesta returnează un CoroutineScope legat de ciclul de viață al Composable, fără a necesita DisposableEffect. Exemplu: pornirea unei cereri de rețea la clic pe buton — scope.launch { viewModel.loadData() }.
Alegerea între Compose și View System — principala întrebare arhitecturală a dezvoltatorului Android în 2026. Ambele tehnologii sunt suportate de Google, dar Compose este direcția principală în care Google investește resurse. View System primește doar remedieri critice și nu se dezvoltă. Diferența se manifestă în sintaxă, gestionarea stării, performanță și timpul de dezvoltare.
| Aspect | Jetpack Compose | View System |
|---|---|---|
| Descriere UI | Funcții Kotlin @Composable | XML + Activity/Fragment |
| Stare | mutableStateOf, StateFlow, redesare automată | findViewById, manual: setText, notifyDataSetChanged |
| Performanță | Intelligent recomposition, randare Canvas | Ierarhie View, measure/layout/draw |
| Animații | animate*AsState, AnimatedVisibility, încorporate | ValueAnimator, ObjectAnimator, Transition |
| Compatibilitate | minSdk 21, punți ComposeView/AndroidView | Toate versiunile |
| Dimensiune APK | +3–5 MB pentru Compose | Fără costuri suplimentare |
Pentru proiecte noi, Google recomandă Jetpack Compose ca standard de dezvoltare UI. View System rămâne pentru suportul codului scris înainte de 2021 și cazurile în care este necesară o dimensiune minimă APK (de exemplu, pentru piețe emergente cu dispozitive entry-level). Compose reduce volumul codului UI cu 30–50% față de View System datorită sintaxei declarative și animațiilor încorporate.
Întrebări frecvente
Da, prin ComposeView în XML. Adăugați dependency pe Compose și înfășurați ecranul sau o parte a acestuia în ComposeView { MyComposable() }. Migrarea se face ecran cu ecran.
Cauza — starea este ridicată prea sus sau se utilizează obiecte mutabile. Remediere: derivedStateOf pentru date derivate și remember pentru referințe stabile.
Utilizați LazyColumn (analog RecyclerView). Elementele sunt create și reutilizate pe măsură ce derulați. Pentru liste complexe cu tipuri diferite de celule — LazyColumn { items(items, key = { it.id }) { ... } }.
Nu, puteți începe direct cu Compose. Cunoașterea View System ajută la suportul codului moștenit, dar Compose este un ecosistem independent cu propria documentație și propriile modele.
Da, Material 3 — este tema standard a Compose din 2023. Se conectează prin implementation("androidx.compose.material3:material3"). Material 2 este considerat învechit.
Rezumat
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.
Citiți și