Recomposition — co to je, přestavba UI při změně stavu

Autor: IT Sectr Publikováno: 2026-06-27 Doba čtení: 7 min

Recomposition je mechanismus Jetpack Compose, který automaticky přestavuje části uživatelského rozhraní při změně dat, bez ruční aktualizace View elementů. Když proměnná stavu, na které závisí Composable funkce, změní hodnotu, Compose restartuje pouze tuto funkci, zatímco zbytek UI stromu zůstává nedotčen. Podle údajů Google Android Developers, 2026, správné pochopení Recomposition umožňuje snížit počet zbytečných překreslení o 40–60%.

Hlavní body

  • Recomposition — restartování Composable funkcí při změně jejich vstupních dat nebo stavu
  • Skipping — přeskočení funkcí, jejichž parametry se nezměnily (porovnání pomocí equals)
  • Stability určuje, zda Compose může funkci přeskočit — stabilní typy jsou porovnávány správně
  • Smart Recomposition restartuje pouze minimální sadu funkcí, ne celý strom
  • Rekompozice nezaručuje překreslení — Layout a Drawing mohou fázi přeskočit

Co je Recomposition v Jetpack Compose

Recomposition je opětovné provedení Composable funkcí, které se již účastnily Composition, s novými hodnotami parametrů nebo stavu. Hlavním cílem rekompozice je synchronizace UI stromu s aktuálními daty bez přestavby celého rozhraní od nuly. Na rozdíl od Composition, který probíhá jednorázově, Recomposition může být spuštěna stokrát během životnosti obrazovky.

Recomposition funguje na principu smart invalidation: Compose sleduje, které State objekty každá Composable funkce čte, a označuje k restartování pouze ty, jejichž závislosti se změnily. Toho je dosaženo pomocí snapshot systému, který zaznamenává všechny operace čtení State během provádění, a Composer, který tyto závislosti mapuje na konkrétní funkce.

Je důležité pochopit: rekompozice neznamená okamžité překreslení obrazovky. Compose pracuje ve třech fázích: Composition (budování popisu UI), Layout (výpočet velikostí a pozic) a Drawing (kreslení na plátno). Pokud se po rekompozici velikosti a poloha prvků nezměnily, fáze Layout může být přeskočena. Pokud se vzhled nezměnil — Drawing je přeskočen. Tato třífázová architektura zajišťuje minimální náklady každé aktualizace UI.

Spouštěče rekompozice: co způsobuje restartování funkcí

Existují tři hlavní spouštěče rekompozice. První — změna State objektu čteného v těle Composable funkce. Když mutableStateOf nebo derivedStateOf změní svou hodnotu, všechny funkce, které zaregistrovaly čtení tohoto State v předchozí kompozici, jsou označeny k restartování.

Druhý spouštěč — změna parametrů Composable funkce při jejím volání z rodičovské funkce. Pokud rodičovská funkce předala novou hodnotu (např. změnil se text nebo číslo), podřízená funkce bude restartována, i když v sobě nečte State. Compose porovnává nové a staré hodnoty parametrů pomocí equals, a pokud jsou stejné — funkce může být přeskočena.

Třetí spouštěč — změna CompositionLocal prostřednictvím CompositionLocalProvider. Všechny funkce, které čtou CompositionLocal pomocí .current, jsou restartovány při změně provideru. Tento mechanismus používá MaterialTheme: změna motivu (světlý/tmavý) způsobuje rekompozici všech komponent, které čtou MaterialTheme.colorScheme.

kotlin
@Composable
fun RecompositionDemo() {
    var counter by remember { mutableStateOf(0) }
    var text by remember { mutableStateOf("Hello") }

    Column {
        Text("Čítač: $counter")  // rekompozice při změně čítače
        Text("Zpráva: $text")    // rekompozice při změně textu

        Button(onClick = { counter++ }) {
            Text("+1")
        }
        Button(onClick = { text = "Svět" }) {
            Text("Změnit text")
        }
    }
}

Stisknutí tlačítka +1 mění counter, což způsobuje rekompozici pouze prvního řádku Text a samotné Column. Druhý řádek Text, který zobrazuje text, není restartován. Taková izolace — výsledek snapshot systému: každá Composable funkce ví jen o těch State objektech, které přečetla.

Optimalizace rekompozice: praktické techniky

Optimalizace rekompozice začíná správným výběrem datových struktur. Používejte neměnné kolekce (listOf, mapOf) místo měnitelných (mutableListOf). Compose porovnává parametry pomocí equals, a pokud se kolekce změnila, ale equals vrátil true — funkce nebude restartována. Pro měnitelné kolekce používejte SnapshotStateList, který implementuje správné sledování změn na úrovni prvků.

Druhá technika — vyčlenění stabilních částí UI do samostatných Composable funkcí. Pokud část obrazovky nezávisí na často se měnícím stavu, vyčleňte ji do samostatné funkce s parametry. Když přijde rekompozice, stabilní funkce obdrží stejné parametry, Compose je porovná a přeskočí provedení. To je výhodnější než restartovat tuto část v rámci velké funkce, kde se část parametrů změnila.

Třetí technika — klíče v LazyColumn. Vždy uvádějte key pro item v LazyColumn, LazyGrid a dalších líných kontejnerech. Klíč umožňuje Compose identifikovat prvky při změně seznamu: přidání, odstranění nebo přeskupení. Bez klíče Compose restartuje všechny prvky seznamu při každé změně, což na velkých seznamech způsobuje znatelnou ztrátu výkonu.

kotlin
// Optimalizovaná struktura: stabilní části vyčleněny samostatně
@Composable
fun OptimizedScreen(items: List<Item>) {
    Column {
        Header()                         // nezávisí na položkách — žádná rekompozice
        Spacer(modifier = Modifier.height(8.dp))
        LazyColumn {
            items(items, key = { it.id }) { item ->
                ItemRow(item = item)   // rekompozice pouze pro změněné položky
            }
        }
    }
}

@Composable
fun Header() {
    Text("Seznam položek", style = MaterialTheme.typography.headlineMedium)
}

@Composable
fun ItemRow(item: Item) {
    Text(item.title)
}

Skipping a Stability v Compose

Skipping je mechanismus, při kterém Compose přeskočí provedení Composable funkce, pokud se všechny její parametry nezměnily. Aby skipping fungoval správně, typy parametrů musí být stabilní (stable). Kotlin kompilátor označuje jako stabilní: primitivní typy (Int, Float, Boolean), String, lambda funkce, stejně jako třídy, jejichž všechna pole jsou stabilní a val.

Stability je anotace @Stable nebo @Immutable, kterou lze přidat vlastním datovým třídám. Pokud třída obsahuje měnitelné pole (var), kompilátor ji považuje za nestabilní a Compose nemůže přeskočit funkce s takovými parametry. Pro třídy s var použijte @Stable, pokud garantujete, že oznámení o změně bude odesláno prostřednictvím snapshot systému.

Stability lze zkontrolovat pomocí přepínače kompilátoru -P "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=. /reports". Ten generuje zprávu se seznamem všech Composable funkcí a jejich parametrů s označením stability. Pokud je parametr nestabilní — skipping pro tuto funkci není možný a bude restartována při každé rekompozici rodiče.

TypStabilitaSkipping
Int, Float, BooleanStabilníAno
StringStabilníAno
LambdaStabilníAno
data class s poli valStabilníAno
data class s poli varNestabilníNe
List<String>NestabilníNe

Všimněte si: List<String> je považována za nestabilní, protože je to rozhraní, nikoli konkrétní implementace. Používejte immutableListOf() z knihovny Kotlin Collections Immutable nebo zabalte seznam do @Stable třídy. Lambda je vždy stabilní, protože její equals porovnává pouze reference, a při vytvoření nové lambdy v místě volání je rodičovská funkce také restartována.

Sledování rekompozic v Android Studio

Pro sledování rekompozic poskytuje Android Studio Layout Inspector s režimem Compose Recomposition Counts. V tomto režimu každá Composable funkce zobrazuje počet rekompozic a důvody restartování. To umožňuje rychle najít funkce, které jsou rekomponovány příliš často, a určit hlavní příčinu — nestabilní parametry nebo zbytečné State závislosti.

Další nástroje: Compose Metrics (sběr statistik pomocí instrumentačních testů) a Recomposition Timer (měření doby provedení každé funkce). Google doporučuje zapínat tyto nástroje ve fázi profilování a vypínat v release sestaveních, protože přidávají režii až 20% na každou rekompozici.

Při analýze rekompozic hledejte vzory unnecessary recomposition: funkce je restartována, ačkoli by se její výstupní UI nemělo změnit. Častou příčinou je používání lambd bez remember, kdy se pokaždé vytváří nový objekt lambdy a Compose považuje parametr za změněný. Řešení: zabalení lambd do remember { } s pevnými zachyceními.

kotlin
// Špatně: nová lambda při každé rekompozici rodiče
@Composable
fun Parent() {
    Child(onClick = { doSomething() })  // pokaždé nová lambda
}

// Dobře: remember stabilizuje lambdu
@Composable
fun Parent() {
    val onClick = remember { { doSomething() } }
    Child(onClick = onClick)  // stejná reference
}

Často kladené otázky

Znamená rekompozice překreslení obrazovky?

Ne, rekompozice je pouze fáze Composition. Po ní následují Layout a Drawing. Pokud se po rekompozici velikosti a poloha prvků nezměnily, Layout a Drawing mohou být zcela přeskočeny, což šetří prostředky GPU.

Jak často může rekompozice probíhat?

Při animacích může rekompozice běžet až 120krát za sekundu (120fps). Pro běžnou interakci — 10–60krát za sekundu. Je důležité, aby každá rekompozice zapadala do rozpočtu snímku (8–16 ms), jinak bude aplikace zpomalovat.

Proč je funkce rekomponována, když se State nezměnil?

Příčinou je změna parametru od rodičovské funkce. Rodič restartuje (z vlastního důvodu) a předá novou hodnotu. Abyste tomu předešli, zkontrolujte stability parametrů a používejte remember pro stabilizaci lambd a vypočítaných hodnot.

Lze vypnout rekompozici pro konkrétní funkci?

Přímé vypnutí neexistuje, ale existuje vynucené přeskočení pomocí readInComposition — State je čten mimo tělo funkce, což neregistruje závislost. Používejte to opatrně: funkce nebude reagovat na změny, což může vést k zastaralému UI.

Co je dražší: Composition nebo Recomposition?

Composition je dražší, protože vytváří všechny sloty a uzly stromu od nuly. Recomposition znovu používá existující sloty a pouze aktualizuje jejich hodnoty. V praxi Composition obrazovky trvá 2–10 ms a rekompozice jednoho prvku — 0.1–1 ms.

Shrnutí

  • Recomposition — selektivní restartování Composable funkcí při změně jejich State nebo parametrů
  • Snapshot system sleduje závislosti funkcí na State a plánuje rekompozici
  • Skipping je možný pouze pro funkce se stabilními parametry (@Stable nebo immutable)
  • Tři spouštěče rekompozice: změna State, změna parametrů, změna CompositionLocal
  • List<T> je považován za nestabilní — používejte neměnné kolekce pro správné přeskočení
  • Layout Inspector zobrazuje počítadla rekompozic pro každou funkci
  • Doporučení: vyčleňujte stabilní části UI do samostatných funkcí a používejte remember pro lambdy

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také