ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ANDROID] Compose CompositionLocal
    ANDROID/JETPACK 2022. 9. 17. 17:49

    CompositionLocal

    https://developer.android.com/jetpack/compose/compositionlocal?hl=ko 

     

    CompositionLocal을 사용한 로컬 범위 지정 데이터  |  Jetpack Compose  |  Android Developers

    CompositionLocal을 사용한 로컬 범위 지정 데이터 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. CompositionLocal은 암시적으로 컴포지션을 통해 데이터를 전달하

    developer.android.com

    일반적으로 Compose에서 데이터는 각 구성 가능한 함수의 매개변수로 UI 트리를 통해 아래로 흐릅니다. 따라서 컴포저블의 종석 항목이 명시적으로 됩니다. 그러나 이 방법은 색상이나 유형 스타일과 같이 매우 자주 널리 사용되는 데이터의 경우 번거로울 수 있습니다.

    @Composable
    fun MyApp() {
        // Theme information tends to be defined near the root of the application
        val colors = …
    }
    
    // Some composable deep in the hierarchy
    @Composable
    fun SomeTextLabel(labelText: String) {
        Text(
            text = labelText,
            color = // ← need to access colors here
        )
    }

    색상을 대부분의 컴포저블에서 명시적 매개변수 종속 항목으로 전달할 필요가 없도록 지원하기 위해 Compose는 CompositionLocal을 제공합니다. 이를 통해 UI 트리를 통해 데이터 흐름이 발생하는 암시적 방법으로 사용할 수 있는 트리 범위의 명명된 객체를 만들 수 있습니다.

     

    CompositionLocal 요소는 일반적으로 UI 트리의 특정 노드의 값과 함께 제공됩니다. 이 값은 구성 가능한 함수에서 CompositionLocal을 매개변수로 선언하지 않아도, 구성 가능한 하위 요소에 사용할 수 있습니다.

     

    CompositionLocal은 머티리얼 테마에서 내부적으로 사용하는 것입니다. MaterialTheme은 나중에 컴포지션의 하위 부분에서 가져올 수 있는 세 개의 CompositionLocal 인스턴스(색상, 서체, 도형)를 제공하는 객체입니다. 이러한 인스턴스는 구체적으로 LocalColors, LocalShapes, LocalTypography 속성으로 MaterialTheme colors, shapes, typography 속성을 통해 액세스할 수 있습니다.

    @Composable
    fun MyApp() {
        // Provides a Theme whose values are propagated down its `content`
        MaterialTheme {
            // New values for colors, typography, and shapes are available
            // in MaterialTheme's content lambda.
    
            // ... content here ...
        }
    }
    
    // Some composable deep in the hierarchy of MaterialTheme
    @Composable
    fun SomeTextLabel(labelText: String) {
        Text(
            text = labelText,
            // `primary` is obtained from MaterialTheme's
            // LocalColors CompositionLocal
            color = MaterialTheme.colors.primary
        )
    }

    CompositionLocal 인스턴스는 컴포지션의 일부로 범위가 지정되므로 트리의 여러 수준에서 다양한 값을 제공할 수 있습니다.

    CompositionLocal의 current 값은 컴포지션에서 범위가 지정된 부분의 상위 요소가 제공한 가장 가까운 값에 대응합니다.

     

    새 값을 ComositionLocal에 제공하려면 CompositionLocalProvider와 CompositionLocal 키를 value에 연결하는 provides 중위 함수를 사용합니다. CompositionLocalProvider의 content 람다는 ComositionLocal의 current 속성에 액세스할 때 제공된 값을 가져옵니다. 새 값이 제공되면 Compose는 CompositionLocal을 읽는 컴포지션의 부분을 재구성합니다.

     

    예를 들어 LocalContentAlpha CompositionLocal에는 UI의 다양한 부분을 강조하거나 강조하지 않기 위해 텍스트나 아이콘에 사용되는 기본 콘텐츠 알파 버전이 포함되어 있습니다. 다음 예에서 CompositionLocalProvider는 컴포지션의 여러 부분에 다양한 값을 제공하는 데 사용됩니다.

    @Composable
    fun CompositionLocalExample() {
        MaterialTheme { // MaterialTheme sets ContentAlpha.high as default
            Column {
                Text("Uses MaterialTheme's provided alpha")
                CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
                    Text("Medium value provided for LocalContentAlpha")
                    Text("This Text also uses the medium value")
                    CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) {
                        DescendantExample()
                    }
                }
            }
        }
    }
    
    @Composable
    fun DescendantExample() {
        // CompositionLocalProviders also work across composable functions
        Text("This Text uses the disabled alpha now")
    }

    위 코드의 결과

    위 모든 예에서 CompositionLocal 인스턴스는 머티리얼 컴포저블에서 내부적으로 사용되었습니다. CompositionLocal의 현재 값에 액세스 하려면 current 속성을 사용합니다. 다음 예에서 Android 앱에서 흔히 사용되는 LocalContext CompositionLocal의 현재 Context 값을 사용하여 텍스트의 형식을 지정합니다.

    @Composable
    fun FruitText(fruitSize: Int) {
        // Get `resources` from the current value of LocalContext
        val resources = LocalContext.current.resources
        val fruitText = remember(resources, fruitSize) {
            resources.getQuantityString(R.plurals.fruit_title, fruitSize)
        }
        Text(text = fruitText)
    }

    자체 CompositionLocal 만들기

    CompostionLocal은 암시적으로 컴포지션을 통해 데이터를 전달하는 도구입니다.

    CompositionLocal 사용을 위한 또 다른 주요 신호는 매개변수가 크로스 커팅이고 구현의 중간 레이어가 그 존재를 인식해서는 안 되는 경우입니다. 이러한 중간 레이거아 인식하도록 하면 컴포저블의 유틸리티가 제한될 수 있기 때문입니다. 예를 들어 Android 권한 쿼리는 내부적으로 CompostionLocal에서 제공됩니다. 미디어 선택 도구 컴포저블은 API를 변경하지 않고 미디어 선택 도구 호출자가 환경에서 사용하는 이러한 추가 컨텍스트를 인식하도록 요구하지 않고도 기기기에서 권한으로 보호되는 콘텐츠에 액세스하는 새로운 기능을 추가할 수 있습니다.

    그러나 CompositionLocal이 항상 최선의 솔루션은 아닙니다. CompositionLocal을 과도하게 사용하지 않는 것이 좋습니다.

    다음과 같은 단점이  있기 때문입니다.

    CompositionLocal은 컴포저블의 동작을 추론하기 어렵게 합니다. 암시적 종속 항목을 만들 때 이를 사용하는 컴포저블의 호출자는 모든 CompositionLocal의 값이 충족되는지 확인해야 합니다.

    또한 이 종속 항목은 컴포지션의 모든 부분에서 변경될 수 있으므로 종속 항목에 관한 명확한 정보 소스가 없을 수도 있습니다. 따라서 문제가 발생할 대 앱을 디버깅하는 것이 어려울 수 있습니다. 컴포지션을 탐색하여 current 값이 제공된 위치를 확인해야 하기 때문입니다. IDE의 Find usages나 Compose 레이아웃 검사기와 같은 도구에서는 이 문제를 완화할 정보를 충분히 제공합니다.

    'ANDROID > JETPACK' 카테고리의 다른 글

    [ANDROID] Support Library, Androidx  (1) 2022.09.23
    [Android] App Architecture  (0) 2022.09.20
Designed by Tistory.