728x90
반응형
여러 @Compose 함수에서 읽거나 수정하는 상태를 공통 상위 컴포저블로 이동 시키는 것
호이스팅 장점
- 상태 중복을 방지하고 버그를 줄임
- 컴포저블을 더 쉽게 재사용 가능
- 테스트 용이
주의점: 상위 요소에서 제어할 필요가 없는 상태는 호이스팅 불필요
잘못된 예시
...
@Composable
fun OnboardingScreen(modifier: Modifier = Modifier) {
// 잘못된 상태 저장 예시
var shouldShowOnboarding by remember { mutableStateOf(true) }
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Welcome to the Basics Codelab!")
Button(
modifier = Modifier.padding(vertical = 24.dp),
onClick = { shouldShowOnboarding = false }
) {
Text("Continue")
}
}
}
@Preview(showBackground = true, widthDp = 320, heightDp = 320)
@Composable
fun OnboardingPreview() {
BasicsCodelabTheme {
OnboardingScreen()
}
}
- shouldShowOnboarding이 함수 내부에 위치하여, 상위 MyApp과 공유가 불가
- 상태를 MyApp에서 관리하고 이벤트만 전달하도록 변경 필요
올바른 호이스팅 적용 예시
@Composable
fun MyApp(modifier: Modifier = Modifier, names: List<String> = listOf("World", "Compose")) {
var shouldShowOnboarding by remember { mutableStateOf(true) } // MyApp에서 상태 저장, by로 권한 위임
Surface(modifier) {
if (shouldShowOnboarding) {
OnboardingScreen(onContinueClicked = { shouldShowOnboarding = false }) // 이벤트 전달
} else {
Greetings()
}
}
}
...
@Composable
fun OnboardingScreen(onContinueClicked: () -> Unit,
modifier: Modifier = Modifier) {
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Welcome to the Basics Codelab!")
Button(
modifier = Modifier.padding(vertical = 24.dp),
onClick = onContinueClicked //이벤트 적용
) {
Text("Continue")
}
}
}
@Preview(showBackground = true, widthDp = 320, heightDp = 320)
@Composable
fun OnboardingPreview() {
BasicsCodelabTheme {
OnboardingScreen(onContinueClicked = {})
}
}
- shouldShowOnboarding을 MyApp으로 이동: 공통 상태 관리
- OnboardingScreen에서 직접 상태를 변경않고 콜백 함수(onContinueClicked)를 사용하여 이벤트만 전달
전체 코드
@Composable
fun MyApp(modifier: Modifier = Modifier, names: List<String> = listOf("World", "Compose")) {
var shouldShowOnboarding by remember { mutableStateOf(true) }
Surface(modifier) {
if (shouldShowOnboarding) {
OnboardingScreen(onContinueClicked = { shouldShowOnboarding = false })
} else {
Greetings()
}
}
}
@Composable
private fun Greetings(
modifier: Modifier = Modifier,
names: List<String> = listOf("World", "Compose")
) {
Column(modifier = modifier.padding(vertical = 4.dp)) {
for (name in names) {
Greeting(name = name)
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier, names: List<String> = listOf("World", "Compose")) {
val expanded = remember { mutableStateOf(false) }
val extraPadding = if (expanded.value) 48.dp else 0.dp
Surface(
color = MaterialTheme.colorScheme.primary,
modifier = modifier.padding(vertical = 4.dp, horizontal = 8.dp)) {
Row(modifier = Modifier.padding(24.dp)) {
Column(modifier = Modifier.weight(1f).padding(bottom = extraPadding)) {
Text(text = "Hello")
Text( text = "$name")
}
ElevatedButton(onClick = { expanded.value = !expanded.value }) {
Text(if (expanded.value) "Show less" else "Show more")
}
}
}
}
@Preview(showBackground = true, widthDp = 320)
@Composable
fun GreetingPreview() {
BasicsCodelabTheme {
Greetings()
}
}
@Composable
fun OnboardingScreen(onContinueClicked: () -> Unit,
modifier: Modifier = Modifier) {
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Welcome to the Basics Codelab!")
Button(
modifier = Modifier.padding(vertical = 24.dp),
onClick = onContinueClicked
) {
Text("Continue")
}
}
}
@Preview(showBackground = true, widthDp = 320, heightDp = 320)
@Composable
fun OnboardingPreview() {
BasicsCodelabTheme {
OnboardingScreen(onContinueClicked = {})
}
}
실행 모습
728x90
반응형
'안드로이드 학습(Compose)' 카테고리의 다른 글
기기 회전과 상태 유지 (0) | 2025.03.04 |
---|---|
LazyColumn, LazyRow의 특징 및 사용 (0) | 2025.03.04 |
Compose에서의 상태 (0) | 2025.03.04 |
열과 행 만들기 (0) | 2025.03.04 |
간단한 버튼 동작 구현해보기 (0) | 2025.03.04 |