注入 ViewModel 时出现 Dagger MissingBinding 错误
Dagger MissingBinding error when injecting ViewModels
我是 dagger 的新手,想用它来注入 ViewModel(以及其他对象,例如存储库)。当我尝试编译应用程序时显示此错误:
e: C:\Project\...\app\build\tmp\kapt3\stubs\debug\com\myapp\di\AppComponent.java:16: 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.
public abstract interface AppComponent {
^
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.myapp.di.ViewModelFactory(viewModels)
com.myapp.di.ViewModelFactory is injected at
com.myapp.di.ViewModelModule.bindViewModelFactory(factory)
androidx.lifecycle.ViewModelProvider.Factory is injected at
com.myapp.ui.activity.MainActivity.viewModelFactory
com.myapp.ui.activity.MainActivity is injected at
dagger.android.AndroidInjector.inject(T) [com.myapp.di.AppComponent ? com.myapp.di.ActivityModule_ContributeMainActivity.MainActivitySubcomponent]
The following other entry points also depend on it:
dagger.android.AndroidInjector.inject(T) [com.myapp.di.AppComponent ? com.myapp.di.ActivityModule_ContributeItemsFrament.ItemsFragmentSubcomponent]
也许有一个愚蠢的错误阻止了编译。
匕首组件:
@Singleton
@Component(modules = [AndroidSupportInjectionModule::class, AppModule::class, DatabaseModule::class, ViewModelModule::class, ActivityModule::class])
interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: MyCustomApplication): Builder
fun build(): AppComponent
}
fun inject(app: MyCustomApplication)
}
应用模块:
@Module
class AppModule {
@Inject
lateinit var app: Application
@Provides
@Singleton
fun provideAppContext(): Context = app.applicationContext
}
活动模块:
@Module
abstract class ActivityModule {
@ContributesAndroidInjector
abstract fun bindMainActivity(): MainActivity
@ContributesAndroidInjector
abstract fun contributeMainFrament(): MainFragment
}
ViewModelModule:
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(MainViewModel::class)
abstract fun mainViewModel(mainViewModel: MainViewModel): ViewModel
}
视图模型工厂:
@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 {
val creator = viewModels[modelClass]
?: viewModels.asIterable().firstOrNull { modelClass.isAssignableFrom(it.key) }?.value
?: throw IllegalArgumentException("unknown model class $modelClass")
return try {
creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
申请class:
class MyCustomApplication : Application(), HasActivityInjector, HasSupportFragmentInjector {
@Inject lateinit var activityInjector: DispatchingAndroidInjector<Activity>
override fun onCreate() {
super.onCreate()
DaggerMainComponent
.builder()
.application(this)
.build()
.inject(this)
}
override fun activityInjector() = activityInjector
}
MainViewModel(请注意,它从 AndroidViewModel
扩展并且需要应用程序上下文):
class MainViewModel @Inject constructor(app: Application, private val repository: MainRepository)
: AndroidViewModel(app) {
主要活动:
class MainActivity : BaseActivity() {
@Inject
internal lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var viewModel: MainViewModel
override fun onCreate(savedState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedState)
viewModel = ViewModelProviders.of(this,viewModelFactory).get(MainViewModel::class.java)
我在组合 Android X
和 Kotlin version 1.3.0
时遇到了同样的问题,Dagger 将无法创建 MultiBindings
。为了解决这个问题,我只是按照以下步骤操作:
a) 将 build.gradle
文件上的 Kotlin 版本更新到 1.3.31:
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin: 1.3.31"
}
b) 清理并重建 项目,为此,在终端中执行以下命令:
$ gradle clean build
或者如果使用 gradle 包装器:
$ ./gradlew clean build
我已经尝试将 kotlin-gradle-plugin
更新为 1.3.31
,但它对我不起作用。
在网上花了一些时间后,我找到了以下适合我的解决方案。
尝试在 Provider<ViewModel>
之前添加 @JvmSuppressWildcards
,如下所示:
@Singleton
@Provides
fun provideViewModelFactory(creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>): ViewModelFactory {
return ViewModelFactory(creators)
}
还有ViewModelFactory
。
class ViewModelFactory(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) :
ViewModelProvider.Factory
我是 dagger 的新手,想用它来注入 ViewModel(以及其他对象,例如存储库)。当我尝试编译应用程序时显示此错误:
e: C:\Project\...\app\build\tmp\kapt3\stubs\debug\com\myapp\di\AppComponent.java:16: 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.
public abstract interface AppComponent {
^
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.myapp.di.ViewModelFactory(viewModels)
com.myapp.di.ViewModelFactory is injected at
com.myapp.di.ViewModelModule.bindViewModelFactory(factory)
androidx.lifecycle.ViewModelProvider.Factory is injected at
com.myapp.ui.activity.MainActivity.viewModelFactory
com.myapp.ui.activity.MainActivity is injected at
dagger.android.AndroidInjector.inject(T) [com.myapp.di.AppComponent ? com.myapp.di.ActivityModule_ContributeMainActivity.MainActivitySubcomponent]
The following other entry points also depend on it:
dagger.android.AndroidInjector.inject(T) [com.myapp.di.AppComponent ? com.myapp.di.ActivityModule_ContributeItemsFrament.ItemsFragmentSubcomponent]
也许有一个愚蠢的错误阻止了编译。
匕首组件:
@Singleton
@Component(modules = [AndroidSupportInjectionModule::class, AppModule::class, DatabaseModule::class, ViewModelModule::class, ActivityModule::class])
interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: MyCustomApplication): Builder
fun build(): AppComponent
}
fun inject(app: MyCustomApplication)
}
应用模块:
@Module
class AppModule {
@Inject
lateinit var app: Application
@Provides
@Singleton
fun provideAppContext(): Context = app.applicationContext
}
活动模块:
@Module
abstract class ActivityModule {
@ContributesAndroidInjector
abstract fun bindMainActivity(): MainActivity
@ContributesAndroidInjector
abstract fun contributeMainFrament(): MainFragment
}
ViewModelModule:
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(MainViewModel::class)
abstract fun mainViewModel(mainViewModel: MainViewModel): ViewModel
}
视图模型工厂:
@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 {
val creator = viewModels[modelClass]
?: viewModels.asIterable().firstOrNull { modelClass.isAssignableFrom(it.key) }?.value
?: throw IllegalArgumentException("unknown model class $modelClass")
return try {
creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
申请class:
class MyCustomApplication : Application(), HasActivityInjector, HasSupportFragmentInjector {
@Inject lateinit var activityInjector: DispatchingAndroidInjector<Activity>
override fun onCreate() {
super.onCreate()
DaggerMainComponent
.builder()
.application(this)
.build()
.inject(this)
}
override fun activityInjector() = activityInjector
}
MainViewModel(请注意,它从 AndroidViewModel
扩展并且需要应用程序上下文):
class MainViewModel @Inject constructor(app: Application, private val repository: MainRepository)
: AndroidViewModel(app) {
主要活动:
class MainActivity : BaseActivity() {
@Inject
internal lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var viewModel: MainViewModel
override fun onCreate(savedState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedState)
viewModel = ViewModelProviders.of(this,viewModelFactory).get(MainViewModel::class.java)
我在组合 Android X
和 Kotlin version 1.3.0
时遇到了同样的问题,Dagger 将无法创建 MultiBindings
。为了解决这个问题,我只是按照以下步骤操作:
a) 将 build.gradle
文件上的 Kotlin 版本更新到 1.3.31:
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin: 1.3.31"
}
b) 清理并重建 项目,为此,在终端中执行以下命令:
$ gradle clean build
或者如果使用 gradle 包装器:
$ ./gradlew clean build
我已经尝试将 kotlin-gradle-plugin
更新为 1.3.31
,但它对我不起作用。
在网上花了一些时间后,我找到了以下适合我的解决方案。
尝试在 Provider<ViewModel>
之前添加 @JvmSuppressWildcards
,如下所示:
@Singleton
@Provides
fun provideViewModelFactory(creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>): ViewModelFactory {
return ViewModelFactory(creators)
}
还有ViewModelFactory
。
class ViewModelFactory(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) :
ViewModelProvider.Factory