private val viewModel = ViewModelProvider(this@SearchFragment).get(SearchViewModel::class.java)
이렇게 프래그먼트에 선언된 ViewModel 생성 코드로부터, 프래그먼트가 ViewModelStore를 get하는 과정을 알아보았다.
// ViewModelProvider.kt
public constructor(
owner: ViewModelStoreOwner
) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))
ViewModelProvider 인스턴스를 생성할 때 위의 생성자가 사용되었다. 여기서 owner.viewModelStore의 implementation 된 곳 중 Fragment.java에 구현된 곳으로 따라가보았다.
// Fragment.java
@NonNull
@Override
public ViewModelStore getViewModelStore() {
// ...
return mFragmentManager.getViewModelStore(this);
}
Fragment에서 getViewModelStore() 메서드를 통해서 ViewModelStore를 가져오는데 이 메서드는 FragmentManager의 getViewModelStore() 메서드와 연결된다.
// FragmentManager.java
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
return mNonConfig.getViewModelStore(f);
}
여기서 mNonConfig.getViewModelStore(f);가 리턴되는데 mNonConfig는
private FragmentManagerViewModel mNonConfig;
같은 파일 내에 선언되어 있는 FragmentManagerViewModel 타입의 필드이다. 그러면 mNonConfig.getViewModelStore(f);를 따라가보자.
// FragmentManagerViewModel.java
final class FragmentManagerViewModel extends ViewModel {
// ...
private final HashMap<String, ViewModelStore> mViewModelStores = new HashMap<>();
// ...
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
if (viewModelStore == null) {
viewModelStore = new ViewModelStore();
mViewModelStores.put(f.mWho, viewModelStore);
}
return viewModelStore;
}
FragmentManagerViewModel이 대체 어떤 클래스인지 맨처음에는 파악이 잘 안되었지만, ViewModel을 상속한 클래스인 것을 보고 굉장히 쉽게 느껴졌다. 우리가 액티비티나 프래그먼트를 만들면 그에 대한 ViewModel 클래스를 만들듯이, 이것도 FragmentManager 클래스에 대한 ViewModel 클래스일 뿐이다.
먼저 FragmentManagerViewModel에서는 ViewModelStore들을 HashMap<String, ViewModelStore> 타입으로 mViewModelStores에 저장하고 있다. 그리고 getViewModelStore() 메서드를 보면 프래그먼트의 개별 UUID인 f.mWho를 통해 해당 프래그먼트의 ViewModelStore를 get하고 있는 것을 알 수 있다.
결론은 프래그먼트는 FragmentManager를 통해서 ViewModelStore를 가져온다는 것을 알 수 있었다.