Composable 함수 내에서 상태를 유지하기 위해 사용됩니다. 이 함수로 생성된 상태는 Composable 함수가 재호출되더라도 변경되지 않습니다. 즉, 상태가 Composable 함수가 호출될 때 한 번 생성되고 그 상태가 유지됩니다. 이는 재호출이 발생하더라도 상태를 유지하고 싶을 때 사용됩니다.
주로 화면 회전과 같은 상태 변경으로 인해 Composable 함수가 다시 생성될 때 상태를 보존하고 복원하기 위해 사용됩니다. 이 함수를 사용하면 Composable 함수가 재생성되더라도 상태를 유지하며, 이전에 입력된 데이터나 상태를 회복하는 데에 특히 유용합니다.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StateHoistingEx() {
/*
rememberSaveable은 Configuration이 변경시 값을 저장할 수 있다.
그러나 캐시를 사용하기 때문에 많은 데이터에 사용하는 것은 권장하지 않는다.
*/
var num by rememberSaveable {
mutableStateOf("0")
}
var result by remember {
mutableStateOf((0.0).toString())
}
Column(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = num,
onValueChange = {
if(it.isBlank()) {
num = ""
result = ""
return@OutlinedTextField
}
val inputNum = it.toFloatOrNull() ?: return@OutlinedTextField // toFloatOrNull() : Float형으로 변경 불가능한 것은 null 리턴
result = (inputNum * inputNum * 3.14).toString()
num = it
}, label = {
Text("반지름")
}
)
OutlinedTextField(
value = result,
onValueChange = {
result = it
},
label = {
Text("원 넓이")
}
)
}
}
@Preview(showBackground = true)
@Composable
fun StateHoistingPreview() {
Compose_exampleTheme {
StateHoistingEx()
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StateHoistingEx() {
/*
rememberSaveable은 Configuration이 변경시 값을 저장할 수 있다.
그러나 캐시를 사용하기 때문에 많은 데이터에 사용하는 것은 권장하지 않는다.
*/
var num by rememberSaveable {
mutableStateOf("0")
}
var resultNum by remember {
mutableStateOf((0.0).toString())
}
numToResultStateless(
num,
resultNum
) {
if (it.isBlank()) {
num = ""
resultNum = ""
return@numToResultStateless // 입력 값이 numToResultStateless에서 리턴되기 때문
}
val inputNum = it.toFloatOrNull()
?: return@numToResultStateless // toFloatOrNull() : Float형으로 변경 불가능한 것은 null 리턴
resultNum = (inputNum * inputNum * 3.14).toString()
num = it
}
}
/*
numToResultStateless는 상태를 가지고 있지 않아서 상태를 변경하지 않는다.
onNumChange: (String) -> Unit 은 num이 변경됬을때 호출할 콜백을 사용해 상위 계층에서 상태를 변경하도록 한다.
이 방식을 통해 numToResultStateless는 상태에 개입하지 않도록 한다.
State관리의 책임은 StateHoistingEx()에서 맡도록 한다.
*/
@Composable
fun numToResultStateless(
num: String,
resultNum: String,
onNumChange: (String) -> Unit
) {
Column(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = num,
onValueChange = onNumChange, // 상태 변경을 onNumChange로 위임
label = {
Text("반지름")
}
)
OutlinedTextField(
value = resultNum,
onValueChange = {},
label = {
Text("원 넓이")
}
)
}
}
@Preview(showBackground = true)
@Composable
fun StateHoistingPreview() {
Compose_exampleTheme {
StateHoistingEx()
}
}
onNumChange: (String) -> Unit
를 변형시켜 손 쉽게 테스트가 가능num
과 resultNum
를 연동할 필요가 사라짐StateHoistingEx()
서 관리하도록 했습니다.numToResultStateless
는 변경이 필요 X)