Hilt는 ViewModel의 의존성 주입을 효과적으로 관리하기 위해 @HiltViewModel
어노테이션과 ViewModelComponent
를 제공한다.
Hilt에서 by viewModels()
델리게이트로 처리된 ViewModel 인스턴스들의 멀티바인딩은 다음과 같이 이루어진다.
Hilt는 @HiltViewModel 어노테이션이 붙은 ViewModel 클래스들을 찾아 자동으로 멀티바인딩 모듈을 생성한다.
@HiltViewModel
class MainViewModel @Inject constructor(...) : ViewModel()
Hilt는 @HiltViewModel 어노테이션이 붙은 ViewModel 클래스에 대해 자동으로 다음과 같은 모듈을 생성한다.
@Module
@InstallIn(ViewModelComponent.class)
public abstract static class BindsModule {
@Binds
@IntoMap
@StringKey("해당viewmodel패키지위치.MainViewModel")
@HiltViewModelMap
public abstract ViewModel binds(MainViewModel vm);
}
여기서 주목할 점은 @StringKey를 사용하여 키 값으로 ViewModel의 전체 클래스 이름을 문자열로 사용한다. 그리고 @HiltViewModelMap 어노테이션을 사용하여 ViewModel 맵을 관리한다. 자세하게 말하자면 ViewModel 인스턴스를 제공하는 Map에 대한 멀티바인딩을 위해 사용하여 각 ViewModel 클래스에 대해 문자열 키(클래스의 전체 이름)와 해당 ViewModel의 Provider를 매핑시킨다.
Hilt는 또한 각 ViewModel에 대한 키를 제공하는 모듈을 생성한다.
@Module
@InstallIn(ActivityRetainedComponent.class)
public static final class KeyModule {
@Provides
@IntoSet
@HiltViewModelMap.KeySet
public static String provide() {
return "해당ViewModel패키지.MainViewModel";
}
}
여기서 ViewModel 키는 왜 ActivityRetainComponent로 설정 되어 있다. ActivityRetainedComponent가 configuration changes에도 생존하는 컴포넌트이고 ViewModel도 마찬가지로 configuration changes를 거쳐 생존해야 하므로, ViewModel의 키를 ActivityRetainedComponent에 제공하는 것이 적절하기 때문이다.
@HiltViewModelMap.KeySet은 Hilt 내부에서 사용되는 한정자(qualifier)로 ViewModel 클래스 이름들의 Set을 멀티바인딩하는 데 사용된다. 이를 통해 Hilt는 어떤 ViewModel들이 사용 가능한지 추적할 수 있다.
Hilt는 이러한 바인딩을 사용하여 내부적으로 HiltViewModelFactory를 구현합니다. 이 팩토리는 멀티바인딩된 Map을 사용하여 필요한 ViewModel 인스턴스를 생성한다.