일종의 디자인 패턴 중 하나로
Stateful한 컴포저블을 Stateless한 컴포저블로 만들기 위한 방법이다.
Stateless하게 변경하는 이유
- Stateful한 컴포저블은 재사용성이 떨어진다.
- Stateless한 컴포저블은 상태를 외부에서 관리하기 때문에 재사용성이 높아진다.
예를 들어 설명하겠다.
자식 컴포저블의 상태를 부모 컴포저블로 옮기는 것이 상태 호이스팅 방법이다.
@Composable
fun KotlinWorldScreen() {
var text by rememberSaveable { mutableStateOf("") }
TextFieldWithTitle(title = "Title", text = text, onTextValueChange = { text = it })
}
@Composable
fun TextFieldWithTitle(title: String, text: String, onTextValueChange: (String) -> Unit) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = title,
modifier = Modifier.padding(bottom = 12.dp),
style = MaterialTheme.typography.h6
)
OutlinedTextField(
value = text,
onValueChange = onTextValueChange
)
}
}
출처:
https://kotlinworld.com/244 [조세영의 Kotlin World:티스토리]
뷰모델은 다음의 특징 덕분에 상태 변수를 더 잘 보관할 수 있다.
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
class MainViewModel : ViewModel() {
var count by mutableStateOf(0) //no remember
fun updateCount(newValue: Int) {
count.value = newValue + 1
}
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val viewModel = viewModel<MainViewModel>() // 간편한 ViewModel 객체 생성
Box(
modifier = Modifier.fillMaxSize(),
) {
val count = viewModel.count
ButtonExample(
count.value,
Modifier.align(Alignment.Center)
) { newValue ->
viewModel.updateCount(newValue)
}
}
}
}
}
@Composable
fun WellnessScreen(
modifier: Modifier = Modifier,
wellnessViewModel: WellnessViewModel = viewModel()
) {
Column(modifier = modifier) {
StatefulCounter()
WellnessTasksList(
list = wellnessViewModel.tasks,
onCheckedTask = { task, checked ->
wellnessViewModel.changeTaskChecked(task, checked)
//람다 구현을 넘겨줌으로써 하위 컴포저블을 Stateless하게 유지
},
onCloseTask = { task ->
wellnessViewModel.remove(task)
}
)
}
}