Jetpack Compose — nowoczesny deklaratywny framework UI od Google do tworzenia aplikacji na Androida, wydany w stabilnej wersji 1.0 w lipcu 2021 roku. Compose zastępuje imperatywne znaczniki XML i system View funkcjami Kotlin z adnotacją @Composable. Według Google I/O (2025), Compose jest używany w 55% nowych projektów na Androida, a średni rozmiar kodu UI zmniejsza się o 30–50% w porównaniu z XML. Framework automatycznie przerysowuje tylko zmienione części ekranu przy zmianie State, eliminując ręczne wywoływanie notifyDataSetChanged czy findViewById.
Najważniejsze
Jetpack Compose — framework UI Google zbudowany na zasadach programowania reaktywnego. Zamiast Activity z układami XML, FragmentManager i ViewBinding, programista opisuje interfejs poprzez funkcje Kotlin z adnotacją @Composable. Compose nie używa LayoutInflater — UI to czyste funkcje Kotlin, kompilowane do kodu bajtowego. Framework składa się z kilku bibliotek: Compose UI (podstawowe komponenty Text, Button, Column, Row), Compose Foundation (Material Design, Gesty, Focus), Compose Material3 (Material You z Dynamic Colors) i Compose Runtime (State, Side Effects, Coroutines). Compose działa na Android API 21+ (Android 5.0) i jest w pełni kompatybilny z istniejącym kodem na View/XML poprzez ComposeView — adapter AndroidView.
View System (2008) wykorzystuje hierarchię obiektów View z ręcznym zarządzaniem: programista tworzy układ XML, znajduje View przez findViewById, implementuje Adapter dla RecyclerView i wywołuje notifyDataSetChanged przy zmianie danych. Compose opisuje UI funkcyjnie: przy zmianie stanu framework restartuje (recompose) tylko zmienione funkcje Composable, oblicza diff i stosuje minimalne zmiany do Canvas. Wydajność Compose jest porównywalna z View System, a w scenariuszach ze złożonymi listami (LazyColumn) często przewyższa RecyclerView dzięki pomijaniu zbędnych elementów przez parametr key. W IT Sectr Compose jest używany w nowych modułach aplikacji Android z minSdk 24+.
@Composable — adnotacja zamieniająca zwykłą funkcję Kotlin w blok budulcowy UI. Funkcje Composable mogą wywoływać inne funkcje Composable, tworząc drzewo komponentów. W przeciwieństwie do View, funkcje Composable domyślnie nie mają stanu — są stateless i przerysowywane przy każdej zmianie parametrów wejściowych lub State. Kompilator (Compose Compiler) transformuje funkcje @Composable w kod, który może być przerwany i wznowiony (positional memoization) — pozwala to Compose restartować tylko zmienione części bez pełnego przebudowywania drzewa.
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
)
}
}Funkcja UserProfile przyjmuje name i avatarUrl jako parametry, buduje wiersz z awatarem i nazwą. Modifier.fillMaxWidth() rozciąga komponent na całą szerokość, .padding(16.dp) dodaje odstępy. MaterialTheme.typography.titleMedium używa systemowego stylu Material 3. Przy zmianie parametrów name lub avatarUrl Compose restartuje UserProfile — ponowne tworzenie komponentu z nowymi wartościami.
State w Compose — to dowolna wartość, której zmiana powoduje rekompozycję (restart) zależnych funkcji @Composable. Podstawowym sposobem jest mutableStateOf(), tworzący MutableState<T> z obsługą systemu snapshotów Compose. Snapshot — mechanizm śledzenia zmian: przy zapisie do State Compose oznacza bieżący Snapshot jako dirty, a planista rekompozycji restartuje tylko funkcje Composable czytające ten State. Dla kolekcji observable używaj mutableStateListOf() i mutableStateMapOf(). Compose obsługuje State z komponentów Lifecycle-Aware przez collectAsState() dla Kotlin Flow i observeAsState() dla LiveData.
@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")
}
}Kod tworzy przycisk «Like» ze stanem liked (Boolean) i count (Int), przechowywanymi przez mutableStateOf(). Po naciśnięciu liked jest odwracany, licznik zwiększa/zmniejsza się — Compose automatycznie restartuje LikeButton. by delegate pozwala używać State jak zwykłej zmiennej: liked = !liked zamiast liked.value = !liked.value. Kolor przycisku zmienia się reaktywnie między primary (polubione) a surfaceVariant (niepolubione).
remember — funkcja Compose buforująca wartość między rekompozycjami. Bez remember każdy restart funkcji Composable tworzy nowy stan (mutableStateOf) — to psuje logikę aplikacji: przy obrocie ekranu lub zmianie nadrzędnego State licznik zostanie zresetowany. remember przyjmuje lambdę-kalkulator i oblicza wartość tylko przy pierwszej kompozycji; przy kolejnych zwraca buforowany wynik. Do resetowania bufora używaj remember(key) — klucz określa, kiedy przeliczyć wartość. remember(key1, key2) przelicza przy zmianie dowolnego klucza. Dla długożyjących stanów (przetrwających obrót ekranu) używaj rememberSaveable — odpowiednik remember z zapisem w Bundle przez SavedStateHandle.
@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 = "Upłynęło: ${seconds}s",
style = MaterialTheme.typography.displayMedium
)
}
}rememberSaveable zachowuje seconds przy obrocie ekranu (zmiana konfiguracji). LaunchedEffect uruchamia korutynę, inkrementującą seconds co sekundę. Przy rekompozycji TimerScreen (co sekundę) seconds nie jest resetowany dzięki rememberSaveable. Używaj zwykłego remember dla stanu, który nie powinien przetrwać zmian konfiguracji (np. flagi animacji).
Modifier — niemutowalny obiekt-kontener implementujący wzorzec Builder do ustawiania wyglądu, zachowania i układu komponentów Composable. Każde wywołanie metody Modifier (.padding(), .width(), .clickable(), .background()) zwraca nowy Modifier z dodanym elementem. Kolejność modyfikatorów ma znaczenie: .padding(16.dp).clickable { } — odstęp jest stosowany przed obsługą kliknięcia, clickable śledzi cały obszar z uwzględnieniem odstępu. .clickable { }.padding(16.dp) — klikalny jest cały obszar przed odstępem, odstęp przesuwa zawartość do środka. Modifier obsługuje implementacje niestandardowe przez then(otherModifier) i compositionLocal do dostępu do ustawień nadrzędnych.
@Composable
fun CardExample() {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.clickable { println("Kliknięto kartę") },
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(
"Deklaratywny UI dla Androida z State i Modifier",
style = MaterialTheme.typography.bodyMedium
)
}
}
}CardExample demonstruje łańcuch Modifier: fillMaxWidth + padding + clickable. Card — komponent Material3 z własnymi ustawieniami elevation i colors. Zagnieżdżony Column ma wewnętrzny padding 16dp. Compose Material3 automatycznie dostosowuje kolory do Dynamic Color (Material You) na Android 12+. Card jest jednym z 30+ wbudowanych komponentów Material3 w Compose.
State hoisting — wzorzec podnoszenia stanu z funkcji Composable do jej wywołującego, czyniący funkcję stateless. Komponent stateless przyjmuje dane i callbacki przez parametry, nie posiadając własnego State. Zwiększa to możliwość ponownego użycia i testowania: komponent można wywołać z różnymi State i przetestować w preview. Google zaleca architekturę: ViewModel + StateFlow (lub MutableStateFlow) + collectAsState() w Compose. ViewModel podnosi stan na poziom ekranu, Compose wyświetla. Efekty uboczne (LaunchedEffect, DisposableEffect) obsługują jednorazowe zdarzenia.
| Komponent | Obowiązek | Technologia |
|---|---|---|
| ViewModel | Przechowywanie State, logika biznesowa | StateFlow, MutableStateFlow |
| Screen Composable | Organizacja ekranu, State hoisting | collectAsState(), Scaffold, LazyColumn |
| Stateless Component | UI bez stanu, czyste wyświetlanie | @Composable parametry + lambdy |
| Side Effect | Jednorazowe działania (snackbar, nawigacja) | LaunchedEffect, SnackbarHostState |
Często zadawane pytania
Układy XML są imperatywne: LayoutInflater ładuje XML, findViewById znajduje View, programista ręcznie aktualizuje tekst/listy. Compose jest deklaratywny: UI opisuje się funkcjami Kotlin @Composable, a framework automatycznie przerysowuje tylko zmienione części przy zmianie State. Compose zmniejsza objętość kodu UI o 30–50% i nie używa XML.
Tak, Google udostępnia Navigation Compose — bibliotekę do deklaratywnej nawigacji między ekranami. NavController zarządza stosem tras, composable() rejestruje ekrany, navArgument przekazuje parametry. Alternatywy: Voyager (społeczność) i Decompose (Badoo). Navigation Compose — oficjalny standard z obsługą deep links i argumentów type-safe.
Modifier — niemutowalny kontener wzorców stylowania (padding, size, clickable, background, border, clip), stosowanych do komponentów Composable. Każde wywołanie zwraca nowy Modifier z dodanym elementem. Kolejność jest ważna: .padding().clickable() stosuje odstęp przed kliknięciem, .clickable().padding() — odwrotnie. Modifier to podstawowy sposób dostosowywania komponentów Compose.
Jetpack Compose obsługuje Android API 21+ (Android 5.0 Lollipop) przez Compose Compiler i Compose BOM. Material 3 (Dynamic Colors) jest dostępny na Android 12+; na starszych wersjach używana jest paleta fallback. W nowych projektach Apple zaleca minSdk 24+ (Android 7.0), co jest w pełni obsługiwane przez Compose.
Google udostępnia Compose UI Test — bibliotekę do testowania na JVM (Desktop) i emulatorze. Główne funkcje: composeTestRule.setContent { } do renderowania komponentu, onNodeWithText() do wyszukiwania elementów, performClick()/performTextInput() do akcji. Testy Espresso są kompatybilne z Compose przez ComposeTestRule, ale Compose UI Test jest preferowanym i szybszym podejściem.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również