我还有一个根组件:
@Singleton
@Component(modules = [AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
ActivityBuilderModule::class])
interface RootComponent : AndroidInjector<DaggerApplication> {
fun inject(myApplication: MyApplication)
override fun inject(photoPartyApplication: DaggerApplication)
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): RootComponent
}
}
在ActivityBuilderModule中:
@Module
abstract class ActivityBuilderModule {
@ContributesAndroidInjector(modules = [MainActivityModule::class,
ViewModelModule::class])
@ActivityScope
abstract fun bindMainActivity(): MainActivity
@ContributesAndroidInjector(modules = [SecondaryActivityModule::class,
ViewModelModule::class,
FragmentBuilderModule::class])
@ActivityScope
abstract fun bindSecondaryActivity(): SecondaryActivity
}
ViewModelModule
是一个简单的模块,可帮助在ViewModel
类中进行构造函数注入,并且由特定实例和@Binds
类型之间的ViewModel
组成。
MainActivityModule
和SecondaryActivityModule
为相应的活动定义特定的依赖关系。
关键是,当我添加此 FragmentBuilderModule 时-编译开始发出错误。堆栈跟踪是下一个:
错误:[Dagger / MissingBinding] some_package。如果没有@Inject构造函数或@Provides注释的方法,则无法提供SpecificDependency。
公共抽象接口RootComponent扩展了dagger.android.AndroidInjector {
^
组件中存在带有匹配键的绑定:some_package.ActivityBuilderModule_BindMainActivity.MainActivitySubcomponent
some_package.SpecificDependency注入到some_package.MainViewModel(specificDependency,…)
some_package.MainViewModel被注入到some_package.ViewModelModule.mainViewModel(viewModel)
Map<Class<? extends ViewModel>, Provider<ViewModel>> is injected at some_package.ViewModelFactory(viewModelProviders)
some_package.ViewModelFactory被注入到some_package.ViewModelModule.bindViewModelFactory(factory)
android.arch.lifecycle.ViewModelProvider.Factory被注入some_package.MyFragment.viewModelFactory
some_package.MyFragment被注入dagger.android.AndroidInjector.inject(T)
[some_package.RootComponent→some_package.ActivityBuilderModule_BindSecondaryActivity.SecondaryActivitySubcomponent→some_package.FragmentBuilderModule_ProvideMyFragmentFactoryMyFragmentSubcomponent]
据我了解,Dagger假设必须为map
的{{1}}正确地构建整个依赖关系图,如果某些Class<? extends ViewModel> -> Provider<ViewModel>
落入{{1} },并且将ViewModels
注入到组件中,那么如果该组件要求任何 factory
,则必须将其交付。同样,为了交付所有factory
,所有依赖项都必须可用(这是不正确的,因为viewmodel
的特定依赖项仅可从viewmodels
获得,这就是匕首在堆栈跟踪之前说。)
有没有解决方法,可以根据需要提供对MainViewModel
的{{1}}的依赖关系,而不是在编译时构建整个图形(这会导致编译时错误)
答案 0 :(得分:0)
首先在RootComponent上添加ViewModelModule
@Singleton
@Component(modules = [AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
ActivityBuilderModule::class,
ViewModelModule::class]) // add this so you don't have to add for every activity
interface RootComponent : AndroidInjector<DaggerApplication> {
fun inject(myApplication: MyApplication)
override fun inject(photoPartyApplication: DaggerApplication)
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): RootComponent
}
}
现在在ActivityBuilderModule中仅添加活动
@Module
abstract class ActivityBuilderModule {
@ContributesAndroidInjector
@ActivityScope
abstract fun bindMainActivity(): MainActivity
}
现在在ViewModelModule中添加所有ViewModel
@Module
abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MainActivityModule::class)
abstract fun bindMainActivityViewModel(mainActivityViewModel: MainActivityModule): ViewModel
}
添加ViewModelKey
@MustBeDocumented
@kotlin.annotation.Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
和ViewModelFactory
@Singleton
class KotlinViewModelFactory @Inject
constructor(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
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 {
Timber.d(creator.toString())
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}