Android/Compose

[Android Compose] ViewModel 사용법

참깨빵위에참깨빵_ 2023. 8. 19. 23:35
728x90
반응형

먼저 뷰모델 의존성을 추가한다.

 

implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")

 

그리고 뷰모델을 만든다. 별다른 API 통신 없이 뷰모델 사용법만 보여주기 위해 간단하게 작성했다.

 

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.lifecycle.ViewModel

class MyViewModel: ViewModel() {
    var backgroundColor by mutableStateOf(Color.White)
        private set

    fun changeBackgroundColor() {
        backgroundColor = Color.Red
    }
}

 

필드로 private setter를 가진 var 변수와 이 변수에 빨간색을 대입하는 함수 하나만 가진 간단한 뷰모델이다.

private set 키워드가 익숙하지 않더라도 보면 대충 무엇인지 유추할 수 있을 것이다. 이 키워드는 코틀린의 var 프로퍼티 값이 외부에서 바뀌는 것을 막기 위한 장치다.

즉 뷰모델의 참조변수를 통해 backgroundColor의 값을 바꿀 수 없도록 하는 것이다. 이를 통해 backgroundColor의 상태를 보호하고 값 변경에 제한을 걸어 안전한 코드를 작성할 수 있게 한 것이다. 이 이상은 이 포스팅의 범위를 넘기 때문에 생략하지만 이것 외에 별 특별한 의미는 없는 키워드니 넘어가도 된다.

아래에 이와 관련한 코틀린 공식문서 링크를 남긴다. Backing fields 챕터에서 조금 위로 올리면 관련 내용이 나온다.

 

https://kotlinlang.org/docs/properties.html#backing-fields

 

Properties | Kotlin

 

kotlinlang.org

 

이후 액티비티는 아래와 같이 작성한다.

 

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.composeprac.viewmodel_in_compose.ui.theme.ComposePracTheme

class ComposeViewModelTestActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposePracTheme {
                val viewModel = viewModel<MyViewModel>(
                    factory = object : ViewModelProvider.Factory {
                        override fun <T : ViewModel> create(modelClass: Class<T>): T {
                            return MyViewModel() as T
                        }
                    }
                )
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = viewModel.backgroundColor
                ) {
                    Column(
                        horizontalAlignment = Alignment.CenterHorizontally,
                        verticalArrangement = Arrangement.Center
                    ) {
                        Button(
                            onClick = {
                                viewModel.changeBackgroundColor()
                            }
                        ) {
                            Text("색깔 변경")
                        }
                    }
                }
            }
        }
    }
}

 

컴포즈를 사용하기 이전에도 뷰모델을 만드는 방법의 하나로 ViewModelProvider.Factory를 사용할 수 있던 것을 이 글까지 찾아 온 사람이라면 대부분 알 것이다. 당연히 컴포즈에서도 이 방식을 사용할 수 있다.

액티비티의 전역 변수로 만들어 두고 여러 곳에서 사용하려면 아래와 같이 사용할 수 있다.

 

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.composeprac.viewmodel_in_compose.ui.theme.ComposePracTheme

class ComposeViewModelTestActivity : ComponentActivity() {

    private val viewModel by viewModels<MyViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposePracTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = viewModel.backgroundColor
                ) {
                    Column(
                        horizontalAlignment = Alignment.CenterHorizontally,
                        verticalArrangement = Arrangement.Center
                    ) {
                        Button(
                            onClick = {
                                viewModel.changeBackgroundColor()
                            }
                        ) {
                            Text("색깔 변경")
                        }
                    }
                }
            }
        }
    }
}

 

by viewModels() 위임 프로퍼티 초기화 함수를 써서 초기화하든, ViewModelProvider를 쓰든 자신의 상황에 맞춰서 사용하면 된다.

또한 뷰모델의 생성자로 repository 또는 인터페이스를 넣어서 레트로핏을 사용하도록 구현할 수 있다. 또한 hilt도 사용할 수 있다. 이 방식들은 컴포즈 이전에서 사용하던 대로 똑같이 쓰면 되기 때문에 자세한 설명은 생략한다.

반응형