rememberUpdatedState 완벽 이해
이진욱
/*
* 2초 후에 onTimeout 실행
**/
@Composable
fun SplashScreen(onTimeout: () -> Unit) {
Box(modifier = modifier.fillMaxSize()) {
LaunchedEffect(Unit) {
delay(2000)
onTimeout()
}
Image(
painterResource(id = R.drawable.ic_crane_drawer),
contentDescription = null
)
}
}
/*
* 빈 람다 {}인 onTimeout을 SpalshScreen에 넘겨준다.
* 0.5초 뒤 onTimeout을 showLandingScreen을 false로 만드는 람다로 변경한다.
**/
@Composable
private fun MainScreen(onExploreItemClicked: OnExploreItemClicked) {
Surface(color = MaterialTheme.colors.primary) {
var showLandingScreen by remember {
mutableStateOf(true)
}
var onTimeout: () -> Unit by remember {
mutableStateOf({ /* empty */ })
}
if (showLandingScreen) {
SplashScreen(onTimeout = onTimeout) // onTimeout = {}
LaunchedEffect(key1 = true) {
delay(500L)
onTimeout = { showLandingScreen = false } // SplashScreen 리컴포지션 발생
}
} else {
CraneHome(onExploreItemClicked = onExploreItemClicked)
}
}
}data class Refer(
var onTimeout: () -> Unit,
)
val refer = Refer {}
@Composable
fun SplashScreen(onTimeout: () -> Unit, modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
// Adds composition consistency. Use the value when LaunchedEffect is first called
refer.onTimeout = onTimeout
LaunchedEffect(Unit) {
delay(SplashWaitTime)
refer.onTimeout()
}
Image(painterResource(id = R.drawable.ic_crane_drawer), contentDescription = null)
}
}@Composable
inline fun <T> remember(crossinline calculation: @DisallowComposableCalls () -> T): T =
currentComposer.cache(false, calculation)@ComposeCompilerApi
inline fun <T> Composer.cache(invalid: Boolean, block: @DisallowComposableCalls () -> T): T {
@Suppress("UNCHECKED_CAST")
return rememberedValue().let {
if (invalid || it === Composer.Empty) {
val value = block()
updateRememberedValue(value)
value
} else it
} as T
}@Composable
fun SplashScreen(onTimeout: () -> Unit, modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
// Adds composition consistency. Use the value when LaunchedEffect is first called
// 정상 동작
val currentOnTimeout by remember { mutableStateOf(onTimeout) }
LaunchedEffect(Unit) {
delay(SplashWaitTime)
currentOnTimeout()
}
Image(painterResource(id = R.drawable.ic_crane_drawer), contentDescription = null)
}
}@Composable
fun <T> rememberUpdatedState(newValue: T): State<T> = remember {
mutableStateOf(newValue)
}.apply { value = newValue }@Composable
fun SplashScreen(onTimeout: () -> Unit, modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
// Adds composition consistency. Use the value when LaunchedEffect is first called
val currentOnTimeout by rememberUpdatedState(onTimeout)
LaunchedEffect(Unit) {
delay(SplashWaitTime)
currentOnTimeout()
}
Image(painterResource(id = R.drawable.ic_crane_drawer), contentDescription = null)
}
}@Composable
private fun Calculation(input: Int) {
val rememberUpdatedStateInput by rememberUpdatedState(input)
val rememberedInput = remember { input }
Text("updatedInput: $rememberUpdatedStateInput, rememberedInput: $rememberedInput")
}
var myInput by remember {
mutableStateOf(0)
}
OutlinedButton(
onClick = {
myInput++
}
) {
Text("Increase $myInput")
}
Calculation(input = myInput)