implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1
Jetpack Compose의 Composable 함수에서 viewModel() 함수로 뷰 모델에 액세스 하기 위해 앱 단위 build.gradle 에 다음 라이브러리를 추가한다.
@Composable
fun Test(testViewModel: TestViewModel = viewModel()) {
Text(text = testViewModel.str)
}
라이브러리 추가 이후 Jetpack Compose로 UI를 구성하는 과정에서 다음과 같이 ViewModel을 참조할 수 있다. 그러나 매개 변수로 전달된 View Model을 하위 Composable 함수에 전달 해서는 안 된다. 안드로이드 문서에서도 화면수준의 컴포저블 함수 (보통 우리가 -Screen이라고 선언하는 컴포저블 함수를 말하는 듯하다)에서 함수를 호출하고 액세스해야 한다고 명시하고 있다.
이와 같은 이유로 다음과 같은 형태의 ViewModel 활용은 Jetpack Compose로 모든 화면이 구성된 앱을 개발할 때 효과적일 것으로 보인다. 기존의 UI와 함께 사용하는 앱에서는 이미 Fragment 나 Activity 단위로 ViewModel이 구성된 상황일 것이다. 그뿐만 아니라 실제로 사용하기 전에는 Compose 에 붙어있는 ViewModelStoreOwner가 언제 생성되고 소멸하는지 확실히 파악할 필요가 있어 보인다.
하위 Composable 함수로 값을 전달해야 할 때는, 기존에 상태를 호이스팅 하는 것처럼 하위 Composable 함수로 값을 전달 하는 것이 좋아 보인다. Composable 함수를 View Model과 함께 사용하면 자주 겪는 어려움은 Preview를 구성하는 데 있다. 위 코드와 같이 간단한 정적 변숫값을 출력하는 것은 문제가 없으나 DB에 접근하거나 네트워크 작업을 하는 등 프리뷰 렌더링이 어려운 경우가 있는데, 이 경우에는 Preview 가능한 Composable 함수와 우리가 실제로 앱 화면을 구성하는 데 사용하는 부분을 분리할 필요가 있다.
@Preview
@Composable
private fun TestScreenPreview() {
TestScreen(str = "Test Screen")
}
@Composable
fun TestScreen(testViewModel: TestViewModel = viewModel()) {
TestScreen(testViewModel.str)
}
@Composable
private fun TestScreen(str: String) {
Text(text = str)
}
다음과 같이 실제로 화면만 구성하는(매개변수로 값을 받아 출력만 하는) Composable 함수와 실제로 View Model을 참조하는 Composable 함수 (외부에서는 이 함수만 접근 가능하므로 실제 코드 작성 시에는 이 함수가 사용된다), Preview를 구성하는 Composable 함수로 각각 분리하면 View Model의 동작과 Preview의 동작은 분리되어 자유로워진다.
비단 이 문제는 View Model을 사용할 때 이외에도 Jetpack Compose로 UI를 구성할 때 Preview를 온전히 활용하려면 모든 View Model에서, 다음과 비슷한 방식으로 구성해야 할 것으로 보인다.
@Preview(showBackground = true, device = Devices.PIXEL_2_XL)
@Composable
fun PlaylistItemPreview() {
PlaylistItem(
playlistData = PlaylistData(
id = UUID.randomUUID().toString(),
name = "이름",
desc = "설명",
state = "state",
authorUid = "authorUid",
likeCount = 0,
resourcesCount = 0,
createdTimestamp = null,
authorProfile = null, thumbnailImageUrls = null
)
)
}
이 코드는 실제로 내가 앱에서 리스트의 아이템에 Preview를 위한 내용을 따로 구성하기 위해 작성하는 코드이다.