11. Jan 2022Android

Jetpack Compose Basics - Ako používať a vytvoriť vlastný CompositionLocal

V 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ší.

Peter ŠulyAndroid developer

Čo je CompositionLocal v Jetpack Compose?

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.

Ako používať CompositionLocal v Jetpack Compose?

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...")
        }
    }
}
Example of using LocalContentColor
Example of using LocalContentColor

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)
    }
}
Otvorená pozícia pre Android developera

Ako vytvoriť vlastný CompositionLocal?

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

  • compositionLocalOf - zmena hodnoty znehodnotí iba obsah, ktorý číta jeho aktuálnu hodnotu
  • staticCompositionLocalOf - čítanie nesleduje Compose. Zmena hodnoty spôsobí, že sa prekomponuje celý obsah lambda, nie len miesta, kde sa číta aktuálna hodnota
// 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
}

Ďalšie články zo série Jetpack Compose Basics:

Peter ŠulyAndroid developer