본문 바로가기
Programming/Android

Android MVVM 에서 ViewModel 의 생성은 ViewModelProvider를 사용해야하는 이유

by ciwhiz 2020. 4. 7.

그 이유는 여기나와있다.

VIewModel의 instance를 어떻게 생성하고, library에서 제공하는 method들의 일부 결함 및 개선 방법에 대한 article

https://proandroiddev.com/view-model-creation-in-android-android-architecture-components-kotlin-ce9f6b93a46b

 

View Model Creation in Android — Android Architecture Components & Kotlin

I have just recently started using Google’s Android Architectural Components, mainly ViewModel and LiveData, specially because now you can…

proandroiddev.com

요약하면, 

viewmodel은 activity 또는 fragment 와 그 lifecycle을 함께 해야하는데, oncreate()해서 viewmodel을 초기화하면,

viewmodel이 자칫 여러번 생성되거나 데이터나 상태의 손실이 발생할 수 있으니,

안드로이드 아키텍쳐가 제공하는 ViewModelProviders component를 통해서 관리해라.

ViewModelProviders 가 lazy delegate 작업을 해서 singleTon 화해서 viewmodel 객체를 리턴해주는 거 같다.

그러나 문제가 하나 있다. 

ViewModelProviders는 내부적으로 empty 생성자를 항상 호출하기 때문에 우리가 만든 Viewmodel의 생성자가

call 되지 않아서, 만약 ViewModel에 empty 생성자가 없다면 최악의 경우에 runtime exception이 발생할 수도 있다.

이를 막기위해서 onCreate()에서 ViewModel이 생성되자마자 public method 로 Viewmodel을 초기화하려는
시도를 해볼 수는 있겠지만 잘못된 방법이다. Activity 나 Fragment의 lifecycle에서 여러 번 호출될 가능성이 있기
때문이다. 

올바른 솔루션은 ViewModel을 위한 Factory를 만들고 ViewmodelProvider에게 전달하는 것이다. 아래가 Factory code

class UserViewModelFactory(val userId: Int) : ViewModelProvider.Factory {
    override fun  create(modelClass: Class): T {
        return UserViewModel(userId) as T
    }
}

ViewModelProvider 에게는 다음과 같이 전달

val vm: UserViewModel by lazy {
        ViewModelProviders.of(this, UserViewModelFactory(intent.getIntExtra(USER_ID, -1))).get(UserViewModel::class.java)
}

2020년 1월 22일

androidx.lifecycle:lifecycle-*:2.2.0가 출시 (변경사항 확인: https://developer.android.com/jetpack/androidx/releases/lifecycle)

ViewModelProviders.of() 지원 중단: ViewModelProviders.of()가 지원 중단되었습니다. Fragment 또는 FragmentActivity를 새로운 ViewModelProvider(ViewModelStoreOwner) 생성자에 전달하면 Fragment 1.2.0을 사용할 때의 기능을 그대로 이용할 수 있습니다.

 

결론: ViewModel은 new Viewmodel() 이러면 XXXX!!!

       ViewModelProviders를 사용하자.