这就是我要提供我的ViewModelFactory
的方式:
@Suppress("UNCHECKED_CAST")
@Singleton
class ViewModelFactory @Inject constructor(
private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T = viewModels[modelClass]?.get() as T
}
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
这就是我绑定ViewModelFactory
的方式:
@Suppress("unused")
@Module
abstract class ViewModelModule {
@Binds
internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(MainViewModel::class)
internal abstract fun mainViewModel(viewModel: MainViewModel): ViewModel
}
在构建过程中收到以下错误:
di/Injector.java:9: error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
我正尝试通过以下方式从我的Activity
接收ViewModelFactory
:
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
答案 0 :(得分:6)
答案 1 :(得分:0)
我最近遇到了同样的问题。 版本 科特琳:1.3.40 Dagger:2.23.2 我尝试遵循本文和here
中提到的解决方案但似乎没有一个起作用。 Dagger的注释处理器不能与KAPT配合使用,并且由于相同的原因,构建失败。 Kotlin issue上也对此进行了更新。
对我来说,将ViewModelKey
和ViewModelFactory
都转换为Java是可行的。
对于Dagger,可以在here中找到跟踪问题。
更新
添加@JvmSuppressWildcards
解决了该问题。代码如下:
private val providers: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
答案 2 :(得分:0)
No need to Downgrade the Kotlin version. As the day of Post my Kotlin version
is : '1.3.40'
Use dagger dependency in build.gradle
apply plugin: 'kotlin-kapt'
//Dagger dependencies
implementation 'com.google.dagger:dagger:2.22.1'
kapt 'com.google.dagger:dagger-compiler:2.22.1'
implementation 'com.google.dagger:dagger-android:2.22'
implementation 'com.google.dagger:dagger-android-support:2.22' // if you use the support libraries
kapt 'com.google.dagger:dagger-android-processor:2.22'
And for Java use the following dagger dependency
//Dagger dependencies
implementation 'com.google.dagger:dagger:2.22.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.22.1'
implementation 'com.google.dagger:dagger-android:2.22'
implementation 'com.google.dagger:dagger-android-support:2.22' // if you use the support libraries
annotationProcessor 'com.google.dagger:dagger-android-processor:2.22'
答案 3 :(得分:-2)
首先ViewModelFactory不应该是Singleton。无论如何要解决此问题,您都应该具有:
一个ViewModelFactory
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 {
val creator = creators[modelClass] ?: creators.entries.firstOrNull {
modelClass.isAssignableFrom(it.key)
}?.value ?: throw IllegalArgumentException("unknown model class $modelClass")
try {
@Suppress("UNCHECKED_CAST")
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
将此工厂绑定到您的模块类中
@Binds
abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
具有ViewModelKey
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
将viewModel绑定到所需的模块中
@Binds
@IntoMap
@ViewModelKey(MyViewModel::class)
abstract fun bindCustomViewModel(viewModel: MyViewModel): ViewModel
然后实现并使用您的viewModel
@Inject
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: MyViewModel by viewModels { viewModelFactory }
此解决方案已通过Kotlin 1.3.72
和最新版本的Dagger2
进行了测试。
另外,请检查https://github.com/android/architecture-components-samples/tree/master/GithubBrowserSample
希望这会对您有所帮助。