[Compose] Preview에 Viewmodel 연결하기

 

Jetpack Compose로 개발 중에 Preview에 Viewmdodel을 적용하는 코드를 작성한다.

 

@Preview(showBackground = true)
@Composable
fun DefaultPreview2() {
    MyFoodDiaryBookAOSTheme {
        MainUi(todayViewModel = TodayViewModel())

    }
}

 

Main화면을 담당하는 MainUi 적용 시, 위와 같이 뷰 모델을 적용해야 했다.

하지만 ComponentActivity 내부에서 viewmodel을 선언해서 사용해야하는데, MainUi 함수의 경우

따로 뷰 모델을 선언할 수 있는 코드를 작성할 수 없다.

따라서 적용하려 하는 뷰 모델의 껍데기 역할을 담당하는 FakeViewModel을 만들어서 Preview에 적용시켰다.

 

 

FakeViewModel

ViewModel에 대한 Preview를 Compose에서 제공하지 않는다.

따라서 Interface나 abstract Class를 생성해서 Fake ViewModel을 구성해야 한다.

 

우선 뷰모델에서 적용할 인터페이스를 생성한다.

 

interface TodayViewModelInterface{
    var _todayCalendar :MutableLiveData<Calendar>
    var _customCalendar : MutableLiveData<CustomCalendar>
    val todayCalendar :LiveData<Calendar>
    val customCalendar : LiveData<CustomCalendar>
}

내가 생성한 인터페이스는 총 4가지 변수를 가지고 있다.

_ 언더바가 붙은 변수는 뷰 모델 내부에 인스턴스를 생성하기 위한 변수이고,

나머지 변수는 인스턴스가 생성되었을 때 초기화 되는 변수이다.

 

todayCalendar는 라이브 데이터로 오늘의 캘린더 정보를 가지고 있다.

customCalendar는 라이브 데이터로 현재 보고있는 캘린더의 날짜 정보를 가지고 있다.

 

인터페이스를 생성하였으니, 생성한 인터페이스를 상속받는 FakeTodayViewModel을 작성했다.

 

//for preview
class FakeTodayViewModel : TodayViewModelInterface{
    override var _todayCalendar: MutableLiveData<Calendar> =
        MutableLiveData<Calendar>()
    override var _customCalendar: MutableLiveData<CustomCalendar> =
        MutableLiveData<CustomCalendar>()
    override val todayCalendar: LiveData<Calendar>
        get() = _todayCalendar
    override val customCalendar: LiveData<CustomCalendar>
        get() = _customCalendar
}

 

이는 단순히 Preview Compose를 위한 가짜 뷰 모델이며, 아무런 값을 가지고 있지 않는 껍데기이다.

 

이 후에 기존의 뷰 모델을 수정한다.

FakeViewModel이 인터페이스를 상속받았으므로,  기존의 뷰 모델인 TodayViewModel도 인터페이스를 상속받도록 한다.

 

@HiltViewModel
class TodayViewModel @Inject constructor():ViewModel(),TodayViewModelInterface{
    override var _todayCalendar = MutableLiveData<Calendar>()
    override val todayCalendar : LiveData<Calendar> get() = _todayCalendar
    override var _customCalendar = MutableLiveData<CustomCalendar>()
    override val customCalendar : LiveData<CustomCalendar> get() = _customCalendar
    init {
        _todayCalendar.value = Calendar.getInstance()
        _customCalendar.value = CustomCalendar(todayCalendar.value!!.time)
        customCalendar.value!!.initBaseCalendar()
    }
}

 

FakeViewModel과 다른점은 이 뷰 모델은 실제로 데이터를 관리해야 하므로, init 변수를 포함하고 있다.

 

Compose 구현

 

이제 기존의 뷰 모델을 사용하는 부분에서는 아래와 같이 인터페이스를 전달해 주는 형식으로

뷰 모델 파라미터를 전달하게 된다.

 

fun MainUi(todayViewModel:TodayViewModelInterface)

 

그리고 Preview에서는 FakeViewModel을 통해서 Compose를 구성한다.

 

@Preview(showBackground = true)
@Composable
fun DefaultPreview2() {
    MyFoodDiaryBookAOSTheme {
        MainUi(todayViewModel = FakeTodayViewModel())

    }
}

 

앱을 테스팅하면, 정상적으로 실행되는 것을 확인할 수 있다.

 

Preview로 해당 View를 확인해보면, 캘린더가 나타나지 않게 되는데,

이는 FakeViewModel 사용 시 데이터를 지정하지 않았기 때문이다.

 

만약에 Preview를 통해서도 ViewModel의 데이터를 관찰하고 싶으면 FakeViewModel 에도 데이터를 추가해주어야 한다.