본문 바로가기
Android/Kotlin

[Android] Compose CompositionLocal

by DnaJ 2022. 3. 30.
반응형

CompositionLocal

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

 

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

CompositionLocal을 사용한 로컬 범위 지정 데이터 CompositionLocal은 암시적으로 컴포지션을 통해 데이터를 전달하는 도구입니다. 이 페이지에서는 CompositionLocal의 자세한 내용과 자체 CompositionLocal을 만

developer.android.com

 

Composition : 구성요소들, 구성

Local : 지역의, (인체의) 일부에 대한

 

CompositionLocal 지역의 구성요소들 입니다.

Compose 에서 사용하는 예

 - MaterialTheme (내부 구성)

 - LocalColors

 - LocalContentColor

 - LocalContext

 - etc....

 

https://play.google.com/store/apps/details?id=com.danchoo.tagalbum&hl=ko

 

태그앨범 - Google Play 앱

사진과 앨범을 태그로 관리하세요. 결혼식, 팬클럽, 동호회등 원하는 카테고리를 만들어 정리해보세요. 사진에 태그를 설정하여 손쉽게 찾아보세요!

play.google.com

 

 

 UI 트리를 통해 데이터 흐름이 발생하는 암시적 방법으로 사용할 수 있는 트리 범위의 명명된 객체를 만들 수 있습니다.

 

Compose트리형태노드 구성을 가지고 있습니다.

상위 노드에서 하위 노드까지 데이터를 전달하기는 사실상 어려울 수 있습니다.

그렇기 때문에 CompositionLocal 을 사용하여 객체를 사용 하는 것을 제공 합니다.

 

Compose 에서 가장 많이 사용하는 Theme

theme 도 내부적으로 CompostionLocal 으로 구성되어 있습니다.

 

@Composable
fun MaterialTheme(
    colors: Colors = MaterialTheme.colors,
    typography: Typography = MaterialTheme.typography,
    shapes: Shapes = MaterialTheme.shapes,
    content: @Composable () -> Unit
) {
    val rememberedColors = remember {
        // Explicitly creating a new object here so we don't mutate the initial [colors]
        // provided, and overwrite the values set in it.
        colors.copy()
    }.apply { updateColorsFrom(colors) }
    val rippleIndication = rememberRipple()
    val selectionColors = rememberTextSelectionColors(rememberedColors)
    CompositionLocalProvider(
        LocalColors provides rememberedColors,
        LocalContentAlpha provides ContentAlpha.high,
        LocalIndication provides rippleIndication,
        LocalRippleTheme provides MaterialRippleTheme,
        LocalShapes provides shapes,
        LocalTextSelectionColors provides selectionColors,
        LocalTypography provides typography
    ) {
        ProvideTextStyle(value = typography.body1) {
            PlatformMaterialTheme(content)
        }
    }
}

 

 위의 코드에서 LocalColor, LocalContentAlpha, LocalIndication, LocalRippleTheme 등 여러가지 CompositionLocal 을 사용합니다.

 

MaterialThemecontent block 안에 있는 Compose 객체들은 MatrialTheme 의 영향을 받게 됩니다.

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            MaterialTheme {
            	// GalleryScreen은 MaterialTheme 의 영향을 받습니다.
                GalleryScreen()
            }
        }
    }
}

 

사용자CompositionLocalProvider 함수를 사용하여

CompositionLocal의 데이터를 재정의 혹은 다른 CompositionLocal을 추가 할수 있습니다.

 

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            // 새로 정의한 Theme
            GlideImageTheme {
            
            	// 사용자가 정의한 LocalImageLoader 를 CompositionLocalProvider 로 적용
                CompositionLocalProvider(LocalImageLoader provides GlideAppImageLoaderImpl()) {
                    GalleryScreen()
                }
            }
        }
    }
}

 

위의 코드는 CompositionLocalProvider를 사용하여 새로 정의한 Theme와 CompositionLocal을 적용하는 코드 입니다.

 

CompositionLocalProvider 내부 구현

@Composable
@OptIn(InternalComposeApi::class)
fun CompositionLocalProvider(vararg values: ProvidedValue<*>, content: @Composable () -> Unit) {
    currentComposer.startProviders(values)
    content()
    currentComposer.endProviders()
}

 

특이하게 TextStyle은 CompositionLocalProvicer로 적용하면 안됩니다.

아래와 같이 ProvideTextStyle사용하여 적용 해야 합니다.

 ProvideTextStyle(value = typography.body1) {
            PlatformMaterialTheme(content)
        }

 

사실상 위의 설명으로만 보면 이걸 어떻게 구현 하는지 잘 모릅니다.

저도 그랬고........

설명은  제 블로그보다 다른 블로그 혹은 Devloper가 낫기 때문에 여기서 때려치우겠습니다!!!! 

 

 

https://smartstore.naver.com/happysiso

 

해피시소마켓 : 네이버쇼핑 스마트스토어

SISO

smartstore.naver.com

 

 

하지만 어떻게 적용해야 하는지 샘플코드를 작성했습니다.

 

@Composable
fun BackTopAppBar(
    modifier: Modifier = Modifier,
    title: @Composable () -> Unit,
    onClickBack: () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    backgroundColor: Color = MaterialTheme.colors.primarySurface,
    contentColor: Color = contentColorFor(backgroundColor)
) {
    TopAppBar(
        modifier = modifier,
        contentColor = contentColor,
        navigationIcon = {
            IconButton(
                imageVector = Icons.Filled.ArrowBack,
                onClick = onClickBack
            )
        },
        title = {
            ProvideTextStyle(value = MaterialTheme.typography.subtitle1) {
                title()
            }
        },
        actions = {
            ProvideTextStyle(value = MaterialTheme.typography.subtitle2) {
                actions()
            }
        }
    )
}

화면에 BackButton 이 많이 사용되기 때문에 따로 Composable로 생성 하여 사용하고 있습니다.

titleactions유동적으로 사용하기 위하여 @Composable () -> Unit (Higher order function - 고차함수) 를 사용했습니다.

(스터디용 토이 프로젝트- 완성되면 store 에 올릴 예정 입니다.ㅎㅎ - 디자이너가 없는게 함정....ㅠㅠ 아는 분한테 부탁 해야 할것 같은데...)

 

*고차 함수  : https://ko.wikipedia.org/wiki/%EA%B3%A0%EC%B0%A8_%ED%95%A8%EC%88%98

* koliin page : https://kotlinlang.org/docs/lambdas.html

 

고차 함수 - 위키백과, 우리 모두의 백과사전

고차 함수(高次函數, higher-order function)는 수학과 컴퓨터 과학에서 적어도 다음 중 하나를 수행하는 함수이다.[1][2][3] 하나 이상의 함수를 인수로 취한다. (예: 절차적 매개변수) 함수를 결과로 반

ko.wikipedia.org

 

ProvideTextStyle을 사용하여 TextStyle변경 했습니다.

하기와 같이 TopAppbar가 필요할때 BackTopAppBar 로 사용을 하게 된다면

title block 에 들어가는 Text는 모두 MatrialTheme.typography.subtitle1적용되게 됩니다.

암시적으로 subtitle1 이 적용되도록 구현되었습니다.

 

Scaffold(
        modifier = modifier.fillMaxSize(),
        topBar = {
            BackTopAppBar(
                title = { 
                
                // Text Style 은 MaterialTheme.typography.subtitle1 이 적용된다  
                	Text(text = "Title") 
                },
                actions = {
                
                    // Text Style 은 MaterialTheme.typography.subtitle2 가 적용된다  
                    Text(text = "TextButton")
                }
            )
        }
    ) {
    	// content 내용
    }

 

또한 하기와 같이 다른 CompositionLocal동시 적용이 가능 합니다.

fun BackTopAppBar(
    modifier: Modifier = Modifier,
    title: @Composable () -> Unit,
    onClickBack: () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    backgroundColor: Color = MaterialTheme.colors.primarySurface,
    contentColor: Color = contentColorFor(backgroundColor)
) {
    TopAppBar(
        modifier = modifier,
        contentColor = contentColor,
        navigationIcon = {
            IconButton(
                imageVector = Icons.Filled.ArrowBack,
                onClick = onClickBack
            )
        },
        title = {
        
        	// LocalContentAlpha, LocalContentColor 적용
            CompositionLocalProvider(
                LocalContentAlpha provides ContentAlpha.medium,
                LocalContentColor provides Color.Red
            ) {
            
            	// TextStyle 적용
                ProvideTextStyle(value = MaterialTheme.typography.subtitle1) {
                    title()
                }
            }

        },
        actions = {
            ProvideTextStyle(value = MaterialTheme.typography.subtitle2) {
                actions()
            }
        }
    )
}

 

 

하기 코드는 CompositionLocal, Hilt, Glide, Compose 를 사용하여 이미지로드하는 것을 공부하는 겸 구현 해봤습니다.

코드에 대한 자세한 설명은 다른 포스팅에서 진행 하겠습니다. (구조는 Coil 을 참고하여 만들었습니다.)

 

sample code로 갤러리 리스트를 보여주도록 했습니다. (물론 버그가 많습니다. webp 적용을 하지 않았습니다 - 재생 안됨....)

 

github : https://github.com/danchoo21/compose-glide-image

 

GitHub - danchoo21/compose-glide-image: Jetpack Compose Glide Image loading library. Only Compose. Support GlideApp and Composit

Jetpack Compose Glide Image loading library. Only Compose. Support GlideApp and CompositionLocalProvider - GitHub - danchoo21/compose-glide-image: Jetpack Compose Glide Image loading library. Only ...

github.com

 

 

https://myseong.tistory.com/46

 

[Android] Compose 와 선언형 UI

요즘 핫한? Compose 를 사용해보고 있습니다!!!! Wow!!!!! 오랜만의 포스팅이라 두서없이 작성이 되었습니다......ㅎㅎ Compose : 구성하다, 작성하다, 합성 출처 : https://en.dict.naver.com/#/search?range=all..

myseong.tistory.com

https://myseong.tistory.com/47

 

[Android] Compose State, Statefull, Stateless, State Hoisting

하기 내용의 일부는 이전 포스팅에서 가지고 왔습니다. 중요하다고 생각이 되기 때문입니다. https://myseong.tistory.com/46 Compose 와 선언형 UI 요즘 핫한? Compose 를 사용해보고 있습니다!!!! Wow!!!!! 오랜.

myseong.tistory.com

https://myseong.tistory.com/48

 

[Android] Compose lifecycle

Compose lifecycle https://developer.android.com/jetpack/compose/lifecycle?hl=ko 컴포저블 수명 주기  | Jetpack Compose  | Android Developers 컴포저블 수명 주기 이 페이지에서는 컴포저블의 수명 주기..

myseong.tistory.com

반응형

댓글