이제 제목을 화면에 연결해 보자. 그렇게 하려면 PlantDetailViewModel을 사용하여 데이터를 로드해야 한다. 이를 위해 컴포즈는 ViewModel 및 LiveData에 대한 통합과 함께 제공된다.

ViewModel

PlantDetailViewModel의 인스턴스가 Fragment에서 사용되므로 PlantDetailDescription에 매개변수로 전달할 수 있다.

Note: ViewModel을 사용할 수 없거나, 해당 종속성을 컴포저블에 전달하고 싶지 않은 경우 컴포저블 내에서 viewModel 함수를 사용하여 ViewModel의 인스턴스를 가져올 수 있다.

컴포저블에는 자체 ViewModel 인스턴스가 없으며, 컴포저블과 해당 컴포즈 코드(액티비티 또는 프레그먼트)를 호스팅하는 Lifecycle Owner 간에 동일한 인스턴스가 공유된다

PlantDetailDescription.kt 파일을 열고 PlantDetailViewModel 매개변수를 PlantDetailDescription에 추가한다.

PlantDetailDescription.kt

@Composable
fun PlantDetailDescription(plantDetailViewModel: PlantDetailViewModel) {
    ...
}

이제 프래그먼트에서 이 컴포저블을 호출할 때 ViewModel의 인스턴스를 전달한다.

PlantDetailFragment.kt

class PlantDetailFragment : Fragment() {
    ...
    override fun onCreateView(...): View? {
        ...
        composeView.setContent {
            MaterialTheme {
                PlantDetailDescription(plantDetailViewModel)
            }
        }
    }
}

LiveData

이를 통해 이미 PlantDetailViewModel의 LiveData<Plant> 필드에 액세스하여 식물 이름을 얻을 수 있다.

컴포저블에서 LiveData를 관찰하려면 LiveData.observeAsState() 함수를 사용하자.

Note: LiveData.observeAsState()는 LiveData 관찰을 시작하고 State 객체를 통해 값을 나타낸다. LiveData에 새 값이 게시될 때마다 반환된 State가 업데이트되어 모든 State.value 사용이 재구성(recomposition)된다.

LiveData에서 내보낸 값이 null일 수 있으므로 null 검사로 래핑해서 사용해야 한다. 그러한 이유 및 재사용성을 위해 LiveData 소비를 분할하고, 다른 컴포저블에서 수신하는 것이 좋은 패턴이다. 따라서 Plant 정보를 표시할 PlantDetailContent라는 새 컴포저블을 만든다.

위의 내용을 감안할 때, LiveData 관찰을 추가한 후 PlantDetailDescription.kt 파일의 모습은 다음과 같다.

PlantDetailDescription.kt

@Composable
fun PlantDetailDescription(plantDetailViewModel: PlantDetailViewModel) {
    // ViewModel의 LiveData<Plant> 필드로 부터 들어오는 값을 관찰한다.
    val plant by plantDetailViewModel.plant.observeAsState()

    // plant가 null이 아니면, 내용을 표시한다.
    plant?.let {
        PlantDetailContent(it)
    }
}

@Composable
fun PlantDetailContent(plant: Plant) {
    PlantName(plant.name)
}

@Preview
@Composable
private fun PlantDetailContentPreview() {
    val plant = Plant("id", "Apple", "description", 3, 30, "")
    MaterialTheme {
        PlantDetailContent(plant)
    }
}

PlantDetailContent가 현재 PlantName을 호출하기 때문에 PlantNamePreview와 동일한 미리보기가 생긴다.

3581b7b21b044e8d.png

이제 ViewModel을 연결하여 Compose에 식물 이름을 표시했다. 다음 몇 섹션에서는 나머지 컴포저블을 빌드하고 유사한 방식으로 ViewModel에 연결한다.

카테고리: Compose

0개의 댓글

답글 남기기

Avatar placeholder

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.