android - Dagger 无法注入 ViewModel 的成员
问题描述
我实现了一个自定义ViewModelFactory
和 Dagger DIViewModel
的成员是由 Dagger 自动注入的,所有代码如下:
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)
}
}
}
迪:
@Suppress("unused")
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
}
@Singleton
@Component(
modules = [
AndroidInjectionModule::class,
AppModule::class,
ViewModelModule::class,
ActivityModule::class
]
)
interface AppComponent: AndroidInjector<App> {
@Component.Builder
abstract class Builder: AndroidInjector.Builder<App>()
}
@Suppress("unused")
@Module
abstract class ActivityModule {
@ContributesAndroidInjector(
modules = [LoginFragmentBuilderModule::class, LoginViewModelModule::class]
)
abstract fun contributeLoginActivity(): LoginActivity
@ContributesAndroidInjector(modules = [])
abstract fun contributeMainActivity(): MainActivity
}
@Suppress("unused")
@Module
abstract class LoginViewModelModule {
@Binds
@IntoMap
@ViewModelKey(AccountViewModel::class)
abstract fun bindAccountViewModel(accountViewModel: AccountViewModel): ViewModel
}
@Suppress("unused")
@Module
abstract class LoginFragmentBuilderModule {
@ContributesAndroidInjector
abstract fun contributeAccountFragment(): AccountFragment
}
@Module
object AppModule {
@JvmStatic
@Provides
fun provideGitHubApi(retrofit: Retrofit): IGitHubApi {
return retrofit.create(IGitHubApi::class.java)
}
// A lot of other providers
}
帐户视图模型::
class AccountViewModel(app: Application) : AndroidViewModel(app) {
@Inject
lateinit var gitHubApi: IGitHubApi
}
我使用教程编写了它,但在编译时出现错误:
e: /test/di/AppComponent.java:8: error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] test.ui.login.models.AccountViewModel cannot be provided without an @Inject constructor or an @Provides-annotated method. This type supports members injection but cannot be implicitly provided.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.contedevel.juke.App> {
^
test.ui.login.models.AccountViewModel is injected at
test.di.LoginViewModelModule.bindAccountViewModel(accountViewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
test.di.ViewModelFactory.<init>(creators)
test.di.ViewModelFactory is injected at
test.di.ViewModelModule.bindViewModelFactory(factory)
androidx.lifecycle.ViewModelProvider.Factory is injected at
test.ui.login.AccountFragment.viewModelFactory
test.ui.login.AccountFragment is injected at
dagger.android.AndroidInjector.inject(T)
component path: test.di.AppComponent → test.di.ActivityModule_ContributeLoginActivity.LoginActivitySubcomponent → test.di.LoginFragmentBuilderModule_ContributeAccountFragment.AccountFragmentSubcomponent
解决方案
首先,Dagger 在这种情况下将如何工作。您正在 AccountViewModel
通过 in 中的参数绑定 的实例bindAccountViewModel
。但是,现在 dagger 将创建 的实例,AccountViewModel
并将绑定到具有键 as 的 Map AccountViewModel::class
。
根据您的堆栈跟踪,Dagger 建议您可以使用构造函数注入或ViewModel
在模块中使用 Provides 方法。从我们当前的实现来看,第二个建议变得普遍,因为我们没有创建 AccountViewModel 的实例。因此,您需要将 IGithubApi 作为构造函数参数传递,AccountViewModel
这在这种情况下将是一个可行的解决方案。
class AccountViewModel @Inject constructor(private val api: IGithubAPI, app: Application) : AndroidViewModel(app)
推荐阅读
- excel - Excel 索引和匹配使用带有通配符的布尔 OR
- jquery - Laravel 8 - jQuery 模态数据未显示
- visual-studio-2019 - VS2019 由于 RemoteInvocationException,Razor 页面中没有智能感知
- python - 无法在 R 3.6.3 中安装 umx 包装
- python - Numba:如何将异构值 Python 字典的内容复制到 Numba Dict 中?
- angular - 如何连接两个响应,依次调用。第二个http调用取决于第一个返回的值?
- javascript - 导入查询会破坏所有 Javascript
- javascript - 如何从 Chrome 中抓取分页网页
- python - 使用python查找另一个数据框中不存在的记录
- python - 美丽的汤 find_all() 不返回所有元素