Compose - rememberUpdatedState의 필요성

2022. 2. 24. 10:00Android/개발 CASE

@Composable
fun HanwhalifeApp() {
    HanwhalifeTheme {
        var showSplashScreen by remember { mutableStateOf(true) }
        if (showSplashScreen) {
            SplashScreen(onTimeout = { showSplashScreen = false })
        } else {
            HanwhalifeHome()
        }
    }
}

@Composable
fun SplashScreen(modifier: Modifier = Modifier, onTimeout: () -> Unit) {
    Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        val currentOnTimeout by rememberUpdatedState(newValue = onTimeout)

        LaunchedEffect(true) {
            // TODO do init something
            delay(SplashWaitTime)
            currentOnTimeout() // (1)
            //onTimeout() // (2)
        }

        Image(painterResource(id = R.drawable.ic_logo), contentDescription = null)
        Icon(
            painterResource(id = R.drawable.ic_logo_text),
            contentDescription = null,
            tint = MaterialTheme.colors.onBackground
        )
    }
}

[이슈] rememberUpdatedState의 필요성에 의문을 가짐.

<의문점 1> HanwhalifeApp 컴포저블에서 사용하는 showSplashScreen을 업데이트하는 onTimeout을 SplashScreen으로 넘겨줘 rememberUpdatedState로 받아서 사용하는데 애초부터 showSplashScreen를 rememberUpdatedState로 사용하면 되지 않을까?

<의문점 2> 1이 안된다면, onTimeout에 대해 rememberUpdatedState를 사용할 필요없이 코드의 (2)처럼 직접 호출해주면 되지 않을까?

 

 

[원인] 

<의문점 1> 외부에서 넘겨주는 param을 받는 경우에는 초기값을 지정할 수 있으므로 사용이 가능하다.(텍스트필드의 값을 넘겨주면 처음 실행 시 값으로 초기화해줄 수 있음) 그러나 위의 코드에서는 param으로 받아오는 값이 없고, 받아오는 경우에도 상수가 아닌 상태에 따른 값을 넘겨야하는데 이때 그것을 판단할 값(SharedPreference라던지.. 좋은 방법인지는 찾아봐야할 듯..)이 주어지지 않는다면 HanwhalifeApp에서 바로 rememberUpdatedState를 사용할 수 없다.(이번 실행에서 splash를 띄웠던 이력이 있는지 없는지)

참고> param으로 넘겨받은 값을 rememberUpdatedState로 사용할 수 있는 경우(초기값을 판단해 param으로 넘겨줄 수 있는 경우)

https://kotlinworld.com/256?category=973278 

 

[Compose State] remember과 rememberUpdatedState를 사용한 상태 관리

remember의 사용과 한계점 Composable에서 remember은 Recomposition이 일어날 때 상태를 관리하기 위해 사용된다.remember의 상태는 remember의 value를 직접 수정해주는 것으로만 가능하다. *by 키워드는 value..

kotlinworld.com

<의문점 2> 현재 코드는 splashScreen을 띄울지 말지를 초기에 셋팅할 수 있는 값이 없으므로 1이 안된다는 전제하에 파람으로 넘겨준 람다값을 직접 실행하면 동일한 결과가 나온다. 그러나 넘겨주는 람다값이 최신화 되기 위해서는 rememberUpdatedState를 쓰는 것이 권장되기 때문에 이처럼 쓴다. 현재 코드처럼 람다값에 변경사항이 없다면 직접 호출을 해주어도 무방할 듯 하다.

참고> rememberUpdatedState의 람다 최신화가 필요한 경우(param이 되는 람다가 업데이트 되는 경우)

https://jetc.dev/slack/2021-08-28-why-need-rememberUpdateState.html

 

Why Do We Need rememberUpdateState()?

 

jetc.dev

 

[해결] 현 코드처럼 splash 실행 조건을 SharedPreference 등의 값으로 저장해놓은 경우가 아니라면 초기값을 결정해 넘겨줄 param을 정할 수 없으므로, remember를 먼저 사용해주는 것이 맞다.(생각해보면 Compose의 상태값을 캡쳐할 수 있는 remember를 쓰기 때문에 SharedPreference를 굳이 써서 상태값을 저장해주는 것은 권장되지 않을 것 같음) 그러나, <의문점 2>에 대해서는 람다가 변하지 않는 한 직접 호출을 통한 작업으로 바꾸어주어도 무방할 듯 하다.(그래도 람다가 변경될 가능성을 염두해두고 rememberUpdatedState를 쓰면 유연성있고, 람다의 최신화가 보장되기 때문에 권장됨)