LazyColumn to funkcja composable w Jetpack Compose do tworzenia pionowych list z leniwym ładowaniem elementów. W przeciwieństwie do Column, LazyColumn tworzy i komponuje tylko widoczne na ekranie elementy, ponownie je wykorzystując podczas przewijania. Według Google Android Documentation, 2025, LazyColumn jest podstawowym narzędziem do wyświetlania dużych zbiorów danych w aplikacjach mobilnych dzięki efektywnemu zarządzaniu pamięcią.
Najważniejsze
LazyColumn to funkcja composable implementująca pionową przewijaną listę z leniwym ładowaniem. W przeciwieństwie do Column, który renderuje wszystkie elementy podrzędne od razu, LazyColumn tworzy tylko elementy znajdujące się w obszarze widoku.
Mechanizm leniwego ładowania w LazyColumn opiera się na ponownym wykorzystaniu elementów: gdy element znika podczas przewijania, jego kompozycja i układ mogą być ponownie użyte dla nowego wyświetlanego elementu. Oszczędza to pamięć i czas procesora, szczególnie na długich listach.
Według Android Developers Blog, 2024, LazyColumn może efektywnie przetwarzać listy dziesiątek tysięcy elementów bez znaczącego spadku wydajności. Każdy element w LazyColumn ma klucz (key), który pomaga Compose identyfikować i zachowywać stan elementu przy zmianach listy.
LazyColumn przyjmuje parametry modifier, state, contentPadding, reverseLayout, verticalArrangement i horizontalAlignment. Zawartość jest określana w bloku lambda przez funkcje DSL items i item.
@Composable
fun SimpleLazyColumn() {
val itemsList = (1..100).toList()
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(16.dp)
) {
items(itemsList) { item ->
Text(text = "Element $item")
}
}
}
Blok DSL LazyColumn udostępnia funkcje items i item do dodawania zawartości. items przyjmuje kolekcję danych, klucz i funkcję fabryczną do tworzenia elementów. item dodaje jeden statyczny element do listy.
itemsIndexed to wariant items, który przekazuje indeks elementu oprócz danych. Jest to przydatne, gdy wymagana jest znajomość pozycji elementu bez oddzielnego obliczania. items(size) przyjmuje tylko liczbę elementów i fabrykę bez powiązania z kolekcją.
Parametr key w items jednoznacznie identyfikuje każdy element. Według Material Design Guidelines, 2025, klucze poprawiają wydajność przy aktualizacji i animacji elementów, ponieważ Compose może śledzić przesunięcie lub zmianę konkretnego elementu po kluczu.
Funkcja items z contentType pozwala LazyColumn optymalizować ponowne wykorzystanie elementów różnych typów. W poniższym przykładzie w jednej liście używane są nagłówki sekcji i zwykłe wiersze.
@Composable
fun MixedItemsList() {
LazyColumn {
item {
Text(
text = "Nagłówek",
style = MaterialTheme.typography.headlineMedium
)
}
items(
items = (1..20).toList(),
key = { it },
contentType = { "item" }
) { item ->
Text(text = "Wiersz $item")
}
}
}
LazyListState to obiekt stanu LazyColumn, który śledzi bieżącą pozycję przewijania, pierwszy widoczny element i przesunięcie. Może być utworzony przez rememberLazyListState() i przekazany do parametru state LazyColumn.
LazyListState udostępnia metody animateScrollToItem i scrollToItem do programowego przewijania do określonego elementu. animateScrollToItem tworzy płynną animację przewijania, a scrollToItem przewija natychmiastowo. Obie metody wymagają wywołania wewnątrz korutyny w CompositionContext.
Według Android Developers, 2024, LazyListState zawiera również layoutInfo, który dostarcza informacji o widocznych elementach — ich indeksach, przesunięciach i rozmiarach. Jest to przydatne do implementacji analityki, śledzenia wyświetleń lub nieskończonego przewijania.
W tym przykładzie LazyColumn jest zarządzany przez LazyListState. Przycisk przewija listę do elementu o indeksie 50 z płynną animacją.
@Composable
fun ScrollableList() {
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()
Column {
Button(
onClick = {
scope.launch {
listState.animateScrollToItem(50)
}
}
) {
Text("Przewiń do 50")
}
LazyColumn(state = listState) {
items((1..100).toList()) { item ->
Text(
text = "Element $item",
modifier = Modifier.padding(8.dp)
)
}
}
}
}
Kluczowym czynnikiem wydajności LazyColumn jest prawidłowe używanie kluczy. Każdy element powinien mieć unikalny stabilny klucz przez parametr key. Bez kluczy Compose nie może poprawnie ponownie wykorzystywać elementów przy zmianie danych, co prowadzi do rekompozycji.
contentType informuje LazyColumn, które elementy mają ten sam typ układu. Gdy dwa elementy z tym samym contentType trafiają do obszaru przetwarzania, LazyColumn może ponownie wykorzystać ich układ bez rekompozycji. Według Android Developers Blog, 2024, contentType poprawia wydajność o 30–50% w listach z różnymi typami elementów.
Dla LazyColumn ważne jest również unikanie niestabilnych parametrów w funkcjach fabrycznych. Za każdym razem, gdy parametr elementu się zmienia, Compose rekomponuje ten element. Używanie remember i derivedStateOf dla stabilnych wartości zmniejsza liczbę rekompozycji.
| Czynnik | Wpływ | Zalecenie |
|---|---|---|
| Klucze (key) | Kluczowy | Zawsze ustawiaj unikalny stabilny key dla items |
| contentType | Znaczący | Określaj typ elementu dla optymalizacji ponownego wykorzystania |
| Rozmiar elementów | Średni | Używaj stałych rozmiarów gdzie to możliwe |
| Zagnieżdżone listy | Krytyczny | Unikaj LazyColumn wewnątrz LazyColumn — używaj LazyVerticalGrid |
stickyHeader to funkcja DSL LazyColumn, która przypina nagłówek sekcji na górze listy podczas przewijania. Gdy następna sekcja dociera do góry, jej nagłówek zastępuje bieżący. To zachowanie jest znane użytkownikom z list kontaktów i kalendarzy.
stickyHeader przyjmuje klucz i funkcję fabryczną, podobnie jak item. W przeciwieństwie do zwykłego item, stickyHeader pozostaje widoczny podczas przewijania zawartości swojej sekcji. Gdy sekcja jest całkowicie przewinięta, nagłówek następnej sekcji wypiera poprzedni.
Według Material Design Guidelines, 2025, sticky header poprawia nawigację w długich listach i zmniejsza obciążenie poznawcze użytkownika. Do implementacji sticky header wystarczy opakować nagłówek sekcji w stickyHeader na właściwej pozycji względem elementów items.
@Composable
fun SectionedList(sections: Map<String, List<String>>) {
LazyColumn {
sections.forEach { (header, items) ->
stickyHeader {
Text(
text = header,
modifier = Modifier.background(Color.White)
.padding(16.dp)
)
}
items(items) { item ->
Text(text = item, modifier = Modifier.padding(8.dp))
}
}
}
}
Często zadawane pytania
Column renderuje wszystkie elementy od razu i nadaje się do list do 20–30 elementów. LazyColumn tworzy tylko widoczne elementy i ponownie je wykorzystuje podczas przewijania, co pozwala pracować z tysiącami elementów bez utraty wydajności.
Użyj Arrangement.spacedBy w parametrze verticalArrangement lub funkcji items z separatorem przez indeks. Dla złożonych separatorów dodaj osobny item z Divider() między elementami listy.
LazyColumn automatycznie rekomponuje się przy zmianie kolekcji danych, jeśli używane są stabilne klucze. Zmiany w danych wykryte przez mutableStateListOf lub StateFlow prowadzą do przerysowania tylko zmienionych elementów.
Bezpośrednie zagnieżdżenie LazyColumn w LazyColumn nie jest zalecane — obie mają niezależne przewijanie, co tworzy konflikt gestów. Zamiast tego używaj zwykłego Column z LazyColumn wewnątrz przewijanej sekcji lub LazyVerticalGrid dla siatek.
Użyj LazyListState.layoutInfo.visibleItemsInfo i porównaj indeks ostatniego widocznego elementu z całkowitą liczbą elementów. Dla nieskończonego przewijania śledź, kiedy ostatni widoczny element zbliża się do końca listy.
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ż