#CompositionLocal Android Developer 공식문서
=>https://developer.android.com/jetpack/compose/compositionlocal?hl=ko
#CompositionLocal
-composable function은 트리구조로 이루어져 있고 보통 state는 트리의 최상단에 위치시키는 state hoisting을 적용시켜주고 state를 아래로 내려주는 방식으로 composable function간에 state를 공유하고는 한다.
-그러나 최상단과 state를 필요로하는 composable function간의 거리가 너무 멀어버리면 state 하나 전달하겠다고 그 사이에 있는 모든 composable의 parameter에 state를 넣어줘야 하는 불편함이 생긴다.
-따라서 CompositionLocal을 활용해서 로컬범위에서 State를 제공해준다면 굳이 사이에 있는 모든 composable function의 parameter에 state를 일일히 넣어줄 필요가 없다.
-그러나 CompositionLocal의 값을 한번 변경하면(비 static일때에만) 기존에 해당 값을 사용하고 있던 녀석들 모두가 영향을 받아서 에러가 발생하거나 의도치 않은 동작을 할 수 있는 문제점이 존재하기 때문에 , 시작점의 하위 요소 하나만 영향을 받는 것이 아니라 하위 요소 모두가 영향을 받을 때에만 사용하는 것이 좋고 기본값에 적절한 데이터 타입을 사용하는 것이 가능할 때에만 사용하는 것이 좋다.
-이런 문제가 발생한하는 등의 이유로 굳이 CompositionLocal을 사용해야되는지 의문이 든다면 명시적으로 Parameter를 전달해주거나 스테이트 호이스팅을 활용해서 상위 컴포저블 함수에서 로직을 실행해도 된다.
-CompositionLocal은 암시적인 데이터라고 볼 수 있다. 명시적인 데이터는 parameter를 통해서 넘겨주기 때문이다. 그런데 parameter에는 없는데 데이터를 넘겨줄 수 있게 해주는 방식이 CompositionLocal이기 때문에 암시적인 데이터라고 부르는 것이다.
-staticCompositionLocalOf를 통해서 생성된 CompositionLocal은 해당 값이 변경되어서 .current로 읽는 값이 변경되어도 Recompositon이 발생하지 않는다.
-따라서 변경되지 않는 값에 사용해야 하며 어쩔수 없이 변경 될 일이 생긴다면 UI 업데이트를 해주는 작업을 별도로 작성해주어야 한다.
-기본값을 넣어주면 기본값에 해당하는 타입으로 자동으로 설정되어 CompositionLocalProvider에서 사용된다. 이때 해당 타입의 데이터만 넣어 줄 수 있음을 주의해서 기본값을 잘 설정해줘야 한다.
fun <T> staticCompositionLocalOf(defaultFactory: () -> T): ProvidableCompositionLocal<T> =
StaticProvidableCompositionLocal(defaultFactory)
val compositionLocalTest1 = staticCompositionLocalOf { 33 }
-compositionLocalOf로 생성된 CompositionLocal은 해당 값이 변경되면 .current로 읽는 값이 변경되면서 해당 값을 읽는 컴포즈함수에서 Recomposition이 발생하게 된다.
-이또한 기본값으로 넣어준 값의 타입으로 자동으로 설정되어서 CompositionLocalProvider에서 사용된다.
fun <T> compositionLocalOf(
policy: SnapshotMutationPolicy<T> =
structuralEqualityPolicy(),
defaultFactory: () -> T
): ProvidableCompositionLocal<T> = DynamicProvidableCompositionLocal(policy, defaultFactory)
var compositionLocalTest2 = compositionLocalOf { "dd" }
-CompositionLocalProvider(변수 이름 provides 제공할 값) { 제공받을 컴포즈 함수 } 이런 형태로 함수가 작성된다.
-변수이름에 제공할 값을 넣어서 제공받을 컴포즈 함수에서 변수이름을 통해서 받아서 사용하면 된다. 변수이름을 통해서 값을 받아올 때는 변수이름 뒤에 .current을 붙혀서 항상 최신의 값을 받아올 수 있게 해주고 가장 가까운 위치에 있는 로컬값을 가져오게 해준다.
@Composable
fun Haha2() {
val haha1 = compositionLocalTest1
var haha2 = compositionLocalTest2
Log.d("haha1" , haha1.current.toString())
Log.d("haha2" , haha2.current)
}
-안드로이드스튜디오 자체적으로 기본적으로 제공해주는 것들이 있는데 LocalContentColor , LocalTextStyle.. 등등의 여러가지 것들이 있다.