Android/Lifecycle
Android ViewModel - ViewModel 생성 과정
강태종
2021. 12. 31. 10:48
안드로이드에서 Fragment가 서로 같은 ViewModel을 공유하기도 하며, Configure Change가 발생해도 ViewModel을 유지합니다. ViewModelProvider를 사용하기 때문에 가능한데 어떻게 동작하는지 확인할 것입니다.
2021.12.06 - [Android/Lifecycle] - Android ViewModel - Activity가 ViewModel을 유지하는 방법
2021.12.29 - [Android/Lifecycle] - Android ViewModel - Fragment가 ViewModel을 유지하는 방법
ViewModelProvider 생성
public constructor(
owner: ViewModelStoreOwner
) : this(owner.viewModelStore, defaultFactory(owner))
/**
* Creates `ViewModelProvider`, which will create `ViewModels` via the given
* `Factory` and retain them in a store of the given `ViewModelStoreOwner`.
*
* @param owner a `ViewModelStoreOwner` whose [ViewModelStore] will be used to
* retain `ViewModels`
* @param factory a `Factory` which will be used to instantiate
* new `ViewModels`
*/
public constructor(owner: ViewModelStoreOwner, factory: Factory) : this(
owner.viewModelStore,
factory
)
UI Controller(Activity, Fragment)에서 ViewModelProvider를 생성할 때 ViewModelStoreOwner와 Factory를 전달합니다.
ViewModelStoreOwner는 ViewModelStore를 참조하는 목적이고, Factory는 ViewModel을 생성하는 목적입니다.
public open class ViewModelProvider(
private val store: ViewModelStore,
private val factory: Factory
)
주 생성자로 직접 ViewModelStore와 Factory를 전달할 수 있으며 어떤 방법으로 생성해도 상관없습니다.
ViewModel 요청
@MainThread
public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
val canonicalName = modelClass.canonicalName
?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
return get("$DEFAULT_KEY:$canonicalName", modelClass)
}
/**
* Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or
* an activity), associated with this `ViewModelProvider`.
*
* The created ViewModel is associated with the given scope and will be retained
* as long as the scope is alive (e.g. if it is an activity, until it is
* finished or process is killed).
*
* @param key The key to use to identify the ViewModel.
* @param modelClass The class of the ViewModel to create an instance of it if it is not
* present.
* @return A ViewModel that is an instance of the given type `T`.
*/
@Suppress("UNCHECKED_CAST")
@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
var viewModel = store[key]
if (modelClass.isInstance(viewModel)) {
(factory as? OnRequeryFactory)?.onRequery(viewModel)
return viewModel as T
} else {
@Suppress("ControlFlowWithEmptyBody")
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = if (factory is KeyedFactory) {
factory.create(key, modelClass)
} else {
factory.create(modelClass)
}
store.put(key, viewModel)
return viewModel
}
get() 함수를 통해 ViewModel을 요청합니다. ViewModelStore에서 ViewModel이 있는지 없는지 확인하여 있으면 재사용하고 없으면 Factory를 통해 생성 후 ViewModelStore에 저장합니다.
마무리
1. ViewModelProvider 생성(ViewModelStoreOwner, Factory)
2. ViewModelStore 참조
3. ViewModel 유무 확인
4. Factory를 통한 ViewModel 생성
5. ViewModel 재사용