본문 바로가기

Android

[Android] Dagger & Hilt ViewModelFactory

Dagger를 통해 DI 구현 중 ViewModelProvider.Factory를 의존성 주입하여 구현하는 방법을 정리해본다.

코드들은 Kotlin으로 작성했다.

 

import androidx.lifecycle.ViewModel
import dagger.MapKey
import java.lang.annotation.*
import java.lang.annotation.Retention
import java.lang.annotation.Target
import kotlin.reflect.KClass

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
class ViewModelFactory @Inject constructor(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) :
    ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        var creator: Provider<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 {
            return creator.get() as T
        } catch (e: Exception) {
            throw IllegalArgumentException(e)
        }
    }

}
@Module
@InstallIn(ApplicationComponent::class)
abstract class ViewModelModule {

    @Binds
    @Singleton
    abstract fun bindsViewModelProviderFactory(viewModelFactory: ViewModelFactory): ViewModelProvider.Factory

    @Binds
    @IntoMap
    @ViewModelKey(LoginViewModel::class)
    abstract fun bindsLoginViewModel(loginViewModel: LoginViewModel): ViewModel
}
@AndroidEntryPoint
class LoginActivity : AppCompatActivity() {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    
    private lateinit var loginViewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        loginViewModel = ViewModelProvider(this, viewModelFactory).get(LoginViewModel::class.java)
		
        ...
    }
}

참고 블로그들

https://dev-vero.tistory.com/4

 

Dagger2 적용하기 (2) - Injection Activity/ViewModel

1. ViewModelKey annotation 생성 @MustBeDocumented @MapKey @Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) internal annotation class ViewModelKey(val value: KClass ) 2. Vie..

dev-vero.tistory.com

https://jaejong.tistory.com/148

 

[Kotlin] @JvmSuppressWildCards 의미

@JvmSuppressWildcards 애노테이션 @JvmSuppressWildcards 코틀린 컴파일러는 제네릭을 기본적으로 List 을 List<? extends String> 형태로 변환합니다 이런형태의 자동변환을 방지하는 방법은 @JvmSuppressWildc..

jaejong.tistory.com