ViewModel

2021. 8. 12. 17:46Android/AAC

  • ViewModel 이란? 기존 MVVM의 ViewModel 역할(UI에 맞는 데이터 제공) + 수명주기
  • ViewModel의 특징
    • UI 컨트롤러(activity, fragment, adapter 등)에 대한 context를 참조하면 안됨
    • context가 필요한 경우 AndroidViewModel을 이용
    • ViewModel을 관리하는 ViewModelStore가 있고, 이를 관리하는 ViewModelStoreOwner가 있음. ViewModelStoreOwner는 ComponentActivity와 Fragment에서 구현하고 있음. 따라서 ViewModel 생성 시 바인딩하는 ViewModelStoreOwner는 Activity나 Fragment가 될 것이고, 이것에 따라 ViewModel의 Scope이 결정됨
  • ViewModel 사용법
    1. build 설정
    2. ViewModel 클래스 생성
    3. (파라미터 있는 경우) ViewModelFactory 생성
    4. UI 컨트롤러에서 참조 생성

1. build 설정

// LiveData와 마찬가지로 프로젝트 생성 시 gradle.properties에 useAndroidX 속성이 true로 설정되며
// 이에 따라 gradle 설정이 자동적으로 진행됨
// 기존 lifecycle-extensions 지원은 중단되었고, 
// livedata, viewmodel, lifecycle runtime, viewmodel savedstate로 세분화 되어 지원되고 있음
android.useAndroidX=true
// gradle.build
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.3.1'

2. ViewModel 클래스 생성

// 일반 ViewModel
// 1. No param
class MainViewModel : ViewModel() {}

// 2. param
class CustomViewModel(val param: String) : ViewModel() {}
// context포함 ViewModel(AndroidViewModel 상속)
// 1. No param
class MainViewModel(application: Application) : AndroidViewModel(application) {}

// 2. param
class CustomAndroidViewModel(application: Application, val param: String) 
	: AndroidViewModel(application) {}

3. (파라미터 있는 경우) ViewModelFactory 생성

// 파라미터 있는 일반 ViewModelFactory
class CustomViewModelFactory(private val param: String) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return if (modelClass.isAssignableFrom(CustomViewModel::class.java)) {
            CustomViewModel(param) as T
        } else {
            throw IllegalArgumentException()
        }
    }
}
// 파라미터 있는 context 포함 ViewModelFactory
class CustomAndroidViewModelFactory(private val application: Application, private val param: String)
    : ViewModelProvider.NewInstanceFactory() {
 
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(AndroidViewModel::class.java)) {
            try {
                return modelClass.getConstructor(Application::class.java, String::class.java)
                    .newInstance(application, param)
            } catch (e: NoSuchMethodException) {
                throw RuntimeException("Cannot create an instance of $modelClass", e)
            } catch (e: IllegalAccessException) {
                throw RuntimeException("Cannot create an instance of $modelClass", e)
            } catch (e: InstantiationException) {
                throw RuntimeException("Cannot create an instance of $modelClass", e)
            } catch (e: InvocationTargetException) {
                throw RuntimeException("Cannot create an instance of $modelClass", e)
            }
        }
        return super.create(modelClass)
    }
}

4. UI 컨트롤러에서 참조 생성

// 일반 ViewModel 참조
// 1. No param
// ViewModelFactory에 ViewModelProvider.NewInstanceFactory() 생략 가능(내부 로직에서 반영됨)
val viewModel = ViewModelProivder(this, ViewModelProvider.NewInstanceFactory())
					.get(MainViewModel::class.java)

// 2. param
val viewModel = ViewModelProivder(this, CustomFactory(param))
					.get(CustomViewModel::class.java)
// context 포함 ViewModel 참조(AndroidViewModelFactory 사용)
// 1. No param
 val viewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application))
    				.get(MainViewModel::class.java)
 
// 2. param
val viewModel = ViewModelProivder(this, CustomAndroidFactory(getApplication(), param))
					.get(CustomAndroidViewModel::class.java)
// 공식 문서에 .get(modelClass) 대신 [modelClass] 사용되어 있으니 참고
val viewModel = ViewModelProvider(this)[MainViewModel::class.java]


// kotlin의 경우 build 설정 후 아래처럼 쓸 수 있음
implementation "androidx.activity:activity-ktx:1.3.1"

// 1. activity
// Use the 'by viewModels()' Kotlin property delegate from the activity-ktx artifact
val model: MyViewModel by viewModels()

// 2. fragment
// Use the 'by activityViewModels()' Kotlin property delegate from the fragment-ktx artifact
private val model: SharedViewModel by activityViewModels()

공식 레퍼 문서 : https://developer.android.com/reference/androidx/lifecycle/ViewModel

 

ViewModel  |  Android 개발자  |  Android Developers

ViewModel public abstract class ViewModel extends Object java.lang.Object    ↳ androidx.lifecycle.ViewModel Known direct subclasses AndroidViewModel Application context aware ViewModel.  ViewModel is a class that is responsible for preparing and mana

developer.android.com

공식 문서 : https://developer.android.com/topic/libraries/architecture/viewmodel?hl=ko 

 

ViewModel 개요  |  Android 개발자  |  Android Developers

ViewModel을 사용하면 수명 주기를 인식하는 방식으로 UI 데이터를 관리할 수 있습니다.

developer.android.com

 

'Android > AAC' 카테고리의 다른 글

Jetpack - Compose  (0) 2021.10.28
Navigation  (1) 2021.08.13
DataBinding  (1) 2021.08.13
LiveData  (0) 2021.08.12
Room  (0) 2021.08.12