24.02.15 Compose ViewModel

KSang·2024년 2월 17일
0

TIL

목록 보기
61/101

오늘은 간만에 다시 컴포즈를 공부해 보려구 한다.

이전까진 뷰를 그려봤는데 이번엔 뷰모델을 구현해보려구한다.

기본 코드

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val data = mutableStateOf(value = "Hello")
            Column(
                modifier = Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally,
            ) {
                Text(
                    text = data.value,
                    fontSize = 30.sp,
                )
                Button(
                    onClick = {
                        data.value = "world"
                    }) {
                    Text(text = "변경")
                }
            }
        }
    }
}

Hello라는 문구가 보이고 버튼이 하나로 구성된 간단한 뷰를 만들었다.

mutableStateOf(value = "Hello")는 컴포즈의 UI상태를 관리 한다.

리멤버 없이 mutableStateOf를 사용하면 경고가 뜨긴 하지만 실행이 가능하다

여기서 버튼을 클릭해보자.

value가 바뀌면서 Hello라는 문구 대신 world가 떠야 할것 같지만 그렇지 않고 Hello라는 문구가 계속 뜨게 된다.

왜 그럴까?

상태가 변경되면 컴포즈에서 다시 컴포지션이 생성되는데 위에 있는 val data = mutableStateOf(value = "Hello")를 타게 되면서 값을 변경해도 Hello가 세팅되게 된다.

그렇기 때문에 이를 remember로 감싸줘야한다.

            val data = remember {
                mutableStateOf(value = "Hello")
                }

이렇게 변경하면 버튼을 클릭했을때 값이 변경된다.

그런데 이전까지 했던 MVVM패턴을 따르면 이런 상태 관리는 뷰모델에서 하게된다.

컴포즈또한 뷰모델에서 할 수 있는데, 기존 코드처럼 뷰모델을 선언 할 수 있다.

ViewModel

class MainActivity : ComponentActivity() {
    private val viewModel by viewModels<MainViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
           ...
}


class MainViewModel: ViewModel() {
    val data = mutableStateOf(value = "Hello")
}

뷰모델을 기존의 방식과 같이 클래스로 선언해서 적용할 수 있다.

뷰모델을 쓰기 때문에 remember을 쓰지 않아도 상태 저장이 가능하다.

Compose ViewModel

컴포즈에선 뷰모델을

    //Compose ViewModel
    implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")

최신 버전은 https://androidx.tech/artifacts/lifecycle/lifecycle-viewmodel-compose/ 여기서 확인 할 수 있다.

이러면 컴포즈 안에서 뷰모델을 선언 할 수 있게 된다.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val viewModel = viewModel<MainViewModel>()
            Column(
                modifier = Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally,
            ) {
            

그리고 뷰모델을 사용하니 직접적으로 값을 변경해주면 안되기에

읽기 전용 모델을 만들고 함수를 호출해서 값을 변경하게 한다.

컴포즈에선 State를 사용해 읽기 전용 메소드를 만든다.

class MainViewModel: ViewModel() {
    private val _data = mutableStateOf(value = "Hello")
    val data: State<String> = _data

    fun changeValue() {
        _data.value = "World"
    }
}
setContent {
            val viewModel = viewModel<MainViewModel>()
            Column(
                modifier = Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally,
            ) {
                Text(
                    text = viewModel.data.value,
                    fontSize = 30.sp,
                )
                Button(
                    onClick = {
                        viewModel.changeValue()
                    }) {
                    Text(text = "변경")
                }
            }
        }

뷰모델만 추가하는 거라 어렵진 않았다

버전 차이로 인해 뭔가 달라지면 어쩌나 걱정했지만 이전 자료와 다르지 않아 문제 없이 작동해서 다행이다.

0개의 댓글