Android/Jetpack Compose
Jetpack Compose CompositionLocal
loppav6
2022. 10. 27. 15:49
먼저 소스와 결과물을 보자.
@Composable
fun View1() {
val viewModel = MyViewModel()
Column {
Button(onClick = { /*TODO*/ }) {
Text(text = "${viewModel.getTitle()} this is Button")
}
View2(viewModel = viewModel)
}
}
@Composable
fun View2(viewModel: MyViewModel) {
TextField(value = "${viewModel.getTitle()} this is TexfField", onValueChange = {})
View3(viewModel = viewModel)
}
@Composable
fun View3(viewModel: MyViewModel) {
OutlinedButton(onClick = { /*TODO*/ }) {
Text(text = "${viewModel.getTitle()} this is OutlinedButton")
}
View4(viewModel = viewModel)
}
@Composable
fun View4(viewModel: MyViewModel) {
OutlinedTextField(value = "${viewModel.getTitle()} this is OutlinedTextField", onValueChange = {})
}
View1은 하위 뷰 View2를 호출한다.
VIew2는 하위 뷰 View3를 호출한다.
View3는 하위 뷰 View4를 호출한다.
View1, View2, View3, View4는 MyViewModel이 필요하다.
최상위 뷰인 View1은 MyViewModel을 View2 파라미터로 전달한다.
View2는 VIew3에게, View3는 View4에게 파라미터를 전달한다.
이런식으로 파라미터를 전달하게 되면 코드관리가 어려워지며 가독성도 좋지 못하다.
Compose에서는 CompositionLocal을 사용하여 해결할 수 있다.
파라미터를 없애고 CompositionLocal을 사용하여 MyViewModel을 사용해보자.
1. MyViewModel을 CompositionLocal에 등록한다.
val LocalMyViewModel = compositionLocalOf<MyViewModel> { error("error") }
2. CompositionLocalProvider 블럭안에 뷰를 종속시킨다.
@Composable
fun View1() {
val viewModel = MyViewModel()
CompositionLocalProvider(LocalMyViewModel provides viewModel) {
Column {
Button(onClick = { /*TODO*/ }) {
Text(text = "${LocalMyViewModel.current.getTitle()} this is Button")
}
View2()
}
}
}
3. LocalMyViewModel.current를 활용하여 MyViewModel에 있는 데이터를 기존과 같이 활용한다.
@Composable
fun View2() {
TextField(
value = "${LocalMyViewModel.current.getTitle()} this is TexfField",
onValueChange = {})
View3()
}
@Composable
fun View3() {
OutlinedButton(onClick = { /*TODO*/ }) {
Text(text = "${LocalMyViewModel.current.getTitle()} this is OutlinedButton")
}
View4()
}
@Composable
fun View4() {
OutlinedTextField(
value = "${LocalMyViewModel.current.getTitle()} this is OutlinedTextField",
onValueChange = {})
}
4. 전체 소스
val LocalMyViewModel = compositionLocalOf<MyViewModel> { error("error") }
class MyViewModel : ViewModel() {
fun getTitle() = "Hello Compose"
}
@Composable
fun View1() {
val viewModel = MyViewModel()
CompositionLocalProvider(LocalMyViewModel provides viewModel) {
Column {
Button(onClick = { /*TODO*/ }) {
Text(text = "${LocalMyViewModel.current.getTitle()} this is Button")
}
View2()
}
}
}
@Composable
fun View2() {
TextField(
value = "${LocalMyViewModel.current.getTitle()} this is TexfField",
onValueChange = {})
View3()
}
@Composable
fun View3() {
OutlinedButton(onClick = { /*TODO*/ }) {
Text(text = "${LocalMyViewModel.current.getTitle()} this is OutlinedButton")
}
View4()
}
@Composable
fun View4() {
OutlinedTextField(
value = "${LocalMyViewModel.current.getTitle()} this is OutlinedTextField",
onValueChange = {})
}
5. 결과