
Zvýš atraktivitu svojej aplikácie: Vstavané hry v mobilných aplikáciách (embedded games)

11. Jan 2022
AndroidV dnešnej epizóde série Jetpack Compose Basics vám ukážem, ako použiť CompositionLocal na implicitné odovzdávanie údajov cez kompozíciu, vďaka čomu bude zoznam parametrov funkcie prehľadnejší.
Ako môžete odovzdať údaje prostredníctvom kompozície? Jedným zo spôsobov je poslať ich, ako parametre do každého composable, ale v prípade farieb alebo typografie môžu byť veci dosť chaotické, pretože ich potrebujete takmer v každom composable.
Druhou možnosťou je použiť CompositionLocal. Je to nástroj na implicitné odovzdávanie údajov kompozíciou. napr. MaterialTheme využíva CompositionLocal na poskytovanie farieb, tvarov a typografie kdekoľvek.
Pozrite si príklad kódu nižšie. Farba textov sa v Text composable nemení priamo, ale používa sa provider LocalContentColor. Táto technika je široko používaná v rámci Jetpack Compose a môže byť užitočná, keď potrebujete zmeniť atribút všetkých composables položiek v scope. Aktuálna hodnota CompositionLocal zodpovedá najbližšej hodnote poskytnutej predkom v špecifikovanej časti kompozície.
CompositionLocalProvider(LocalContentColor provides Color.Blue) {
// content color for all components in this scope is blue
Text(text = "Lorem")
CompositionLocalProvider(LocalContentColor provides Color.Red) {
// content color for all components in this scope is blue
Text(text = "ipsum")
Text(text = "dolor")
CompositionLocalProvider(LocalContentAlpha provides 0.2f) {
// alpha of all components in this scope is 0.2f
Text(text = "sit...")
}
}
}
Ak je vaša otázka - Ako môže Text composable vedieť, ktorú farbu alebo alfu použiť? - odpoveď je v implementácii Text composable. Farba textu sa určí pomocou LocalContentColor.current, pokiaľ caller nešpecifikuje atribút color.
val textColor = color.takeOrElse {
style.color.takeOrElse {
LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
}
}
Po prvé, CompositionLocal skutočne dáva zmysel, najmä ak ho môže potenciálne použiť ktorýkoľvek potomok, nie niekoľko z nich. Radšej si dvakrát rozmyslite, či ho naozaj chcete vytvoriť alebo len použiť explicitné parametre. Nie je to vždy najlepšie riešenie a neodporúča sa to preháňať. Nevýhodou je, že je ťažšie zabezpečiť, aby bola splnená hodnota každého CompositionLocal, keď vznikajú implicitné závislosti.
Po druhé, v CompositionLocal by mala byť vždy nejaká hodnota, pričom pri vytváraní by mala byť poskytnutá vaša predvolená hodnota.
Existujú 2 možnosti na vytvorenie CompositionLocal
// Definition with default value
val LocalPaddings = compositionLocalOf { PaddingValues(0.dp) }
.
.
.
// Using CompositionLocal App-wide
CompositionLocalProvider(LocalPaddings provides PaddingValues(24.dp)) {
/*
your app composables...
*/
}
Čítanie z vytvorených LocalPaddings môže vyzerať takto. Box v príklade nižšie má teraz paddings pre celú aplikáciu - PaddingValues (24.dp).
Box(
modifier = Modifier.padding(LocalPaddings.current)
){
// some composable padded by 24.dp
}