목표
- ViewModel이 저장 및 호출되는 방법에 대해 간략하게 이해한다.
이 글은 자바 및 안드로이드에 대한 많은 이해가 필요하므로, 이해가 안가면 3번 글로 넘어가도 무방하다.
ViewModelProvider을 이용한 초기화
ViewModel 인스턴스를 만들기 위해서는 ViewModelProvider을 사용해야 한다.
가장 기본적인 ViewModel을 초기화 하는 방법을 다룬 아래 코드를 살펴보도록 하자.
class MainActivity : AppCompatActivity(), View.OnClickListener {
val viewModel = ViewModelProvider(this@MainActivity).get(MainViewModel::class.java)
..
}
앞에 1장에서 배웠듯이 ViewModel은 은 자신의 데이터가 유지되어야 할 View(Activity, Framgent)를 알아야 한다. 위 코드를 직관적으로 해석하면 ViewModelProvider의 파라미터로 MainActivity(View)를 전달하고 그로부터 ViewModel Class를 넣어 ViewModel을 get 한다. 우리가 1번 글에서 배웠던 내용에 따르면, 이로부터 생겨난 ViewModel은 MainActivity의 Lifecycle을 따르는 ViewModel이 될 것이라 예측할 수 있다. 그러면 이것이 어떻게 동작하는지 살펴보자.
ViewModelProvider 해석
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public interface ViewModelStoreOwner {
..
@NonNull
ViewModelStore getViewModelStore();
}
ViewModelProvider는 ViewModelStoreOwner 인터페이스를 구현하는 인스턴스를 인자로 받는다. 우리는 이로부터 Activity와 Fragment가 ViewModelStoreOwner 인터페이스를 구현함을 알 수 있고 View(Activity, Fragment)인스턴스의 Lifecycle을 이용해 ViewModel을 제공함을 알 수 있다.
*더 자세한 사항은 범위를 넘어가니 다루지 않는다.
또한 NewInstanceFactory.getInstance() 로부터 ViewModelProvider가 ViewModelStoreOwner에 대해 SingleTon으로 만들어짐을 알 수 있다.
get메서드 내부는 다음과 같다. 인자를 하나 받는 get 메서드를 타고 들어가면 인자를 두 개 받는 get 메서드가 나오게 되는데 그 코드는 다음과 같다.
*중간에 Factory 메서드가 나오는데 이해를 위해 해당 메서드는 모두 생략한다.
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
..
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
class로부터 받은 canonicalName(정식이름)을 key로 두고 ViewModel을 저장하는 Map인 ViewModelStore에 해당 key값에 대해 viewModel 값을 저장한 다음 만들어진 viewModel을 return 한다. 여기서 보아야 할 것은 ViewModel은 같은 ViewModelStore에 대해 key-value 쌍으로 ViewModel을 저장한다는 점이다.
즉, 같은 ViewModelStoreOwner(Acitivty, Fragment)에 대해 같은 이름의 ViewModel 클래스를 get하면 같은 인스턴스가 반환된다.
정리
- ViewModel을 만들기 위해서는 ViewModelStoreOwner 인터페이스를 구현하는 Lifecycle을 가진 View(Activity, Fragment)가 필요하다.
- 만들어진 ViewModel은 ViewModelStoreOwner인터페이스 내부의 ViewModelStore(ViewModel을 Key Value 쌍으로 저장하는 인스턴스)에 저장된다.