상황
Dagger로 ViewModel를 다루고 싶었다. 그러나 자꾸 해당 에러 메시지가 발생했다.
error: Dagger does not support injecting maps of disallowed types: java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,dagger.internal.Provider<androidx.lifecycle.ViewModel>>
Dagger version은 2.50
내가 짠 코드
참고한 포스트
Leveraging Dagger for ViewModel Dependency Injection in Android
Dependency injection (DI) is a fundamental technique in software engineering that enhances the modularity, flexibility, and testability of…
medium.com
내가 짠 코드와 비슷한 예제
class ViewModelFactory @Inject constructor(
private val creators: @JvmSuppressWildcards Map<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
var creator: Provider<out ViewModel>? = creators[modelClass]
if (creator == null) {
for ((key, value) in creators) {
if (modelClass.isAssignableFrom(key)) {
creator = value
break
}
}
}
if (creator == null) throw IllegalArgumentException("Unknown model class $modelClass")
try {
@Suppress("UNCHECKED_CAST")
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
@MustBeDocumented
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Module
public abstract class ViewModelModule {
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory);
@Binds
@IntoMap
@ViewModelKey(MyActivityViewModel.class)
abstract ViewModel bindMyActivityViewModel(MyActivityViewModel viewModel);
}
앱 빌드 시 나오는 에러 메시지
error: Dagger does not support injecting maps of disallowed types: java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,dagger.internal.Provider<androidx.lifecycle.ViewModel>>
ViewModelFactory에 주입되는 Map인 creator에서 자꾸 이슈가 생겼다.
도와줘 Gemini
(이미 ChatGPT와 실컷 삽질하고 찾은 Gemini)
제네릭 이슈였다.
마지막 삽질
Gemini가 알려준, 무식한 듯 하지만 선택지가 없어서 했던 작업. 수동으로 map을 생성해 주입하도록 짰다.
@Module
public abstract class ViewModelModule {
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory);
// 추가한 부분
// 아래 코드는 ViewModel이 많으면 번거롭지만, 오류를 우회할 수 있습니다.
@Provides
@Singleton // 또는 적절한 Scope
static Map<Class<? extends ViewModel>, Provider<ViewModel>> provideViewModelCreators(
// Dagger가 각 ViewModel에 대한 Provider를 주입해 줄 것입니다.
Provider<MyActivityViewModel> myActivityViewModelProvider
// 다른 ViewModel Provider들도 여기에 추가합니다. 예:
// Provider<AnotherViewModel> anotherViewModelProvider
) {
Map<Class<? extends ViewModel>, Provider<ViewModel>> creators = new HashMap<>();
creators.put(MyActivityViewModel.class, (Provider<ViewModel>) myActivityViewModelProvider);
// 다른 ViewModel들도 추가합니다. 예:
// creators.put(AnotherViewModel.class, (Provider<ViewModel>) anotherViewModelProvider);
return creators;
}
// 위에서 맵을 수동으로 제공하므로, 아래 @Binds @IntoMap 부분은 제거해야 합니다.
// @Binds
// @IntoMap
// @ViewModelKey(MyActivityViewModel.class)
// abstract ViewModel bindMyActivityViewModel(MyActivityViewModel viewModel);
}
그리고 나온 에러 메시지
error: Dagger disallows injecting the type: dagger.internal.Provider<com.dnt7.threeW.mypage.PremiumActivityViewModel>
도와줘 Gemini
즉, Provider<ViewModel> 대신 그냥 ViewModel을 쓰라는 이야기
해결
1. ViewModelModule은 원복
2. ViewModelFactory 수정
class ViewModelFactory @Inject constructor(
private val creators: @JvmSuppressWildcards Map<Class<out ViewModel>, ViewModel>
) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
var creator: ViewModel? = creators[modelClass]
if (creator == null) {
for ((key, value) in creators) {
if (modelClass.isAssignableFrom(key)) {
creator = value
break
}
}
}
if (creator == null) throw IllegalArgumentException("Unknown model class $modelClass")
try {
@Suppress("UNCHECKED_CAST")
return creator as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
이게 된다!
'빈 구멍 채우기' 카테고리의 다른 글
[기술 블로그 읽기] The Curse of Knowing How, or; Fixing Everything (0) | 2025.05.21 |
---|---|
[삽질기록] 코드로 기입하지 않은 padding 값이 이미지에 적용되는 이슈 (0) | 2025.04.16 |
[삽질기록] 버전이 오래된 라이브러리가 자꾸 Failed to resolve 된다. (1) | 2025.04.04 |
[삽질기록] 안드로이드 스튜디오가 자꾸 프록시 설정 다이얼로그를 띄운다. (0) | 2025.04.02 |
[삽질기록][Paging] RemoteMediator 무한 load 이슈 (0) | 2025.03.04 |