Dagger2 无法提供 activity 对匕首的依赖
Dagger2 Can't provide dependency of activity to dagger
MainActivity cannot be provided without an @Inject constructor or an
@Provides-annotated method. This type supports members injection but
cannot be implicitly provided.
我用的是dagger-android,我通过AndroidInjection.inject(this)注入了MainActivity,但是在Module中还是不可用。我准备了示例项目:https://github.com/deepsorrow/test_daggerIssu.git,文件如下:
FactoryVmModule:
@Module
class FactoryVmModule {
@Provides
@Named("TestVM")
fun provideTestVM(
activity: MainActivity, // <--- dagger can't inject this
viewModelFactory: ViewModelFactory
): TestVM =
ViewModelProvider(activity, viewModelFactory)[TestVM::class.java]
}
MainActivityModule:
@Module
abstract class MainActivityModule {
@ContributesAndroidInjector
abstract fun injectMainActivity(): MainActivity
}
MainActivity(使用 DaggerAppCompatActivity):
class MainActivity : DaggerAppCompatActivity() {
@Named("TestVM")
@Inject
lateinit var testVM: TestVM
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
测试应用程序:
class TestApplication : Application(), HasAndroidInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
override fun onCreate() {
super.onCreate()
DaggerAppComponent.create().inject(this)
}
override fun androidInjector() = dispatchingAndroidInjector
}
应用程序组件:
@Component(modules = [AndroidInjectionModule::class, MainActivityModule::class, ViewModelModule::class, FactoryVmModule::class])
interface AppComponent {
fun inject(application: TestApplication)
}
dagger.android does do this automatically: See the explicit version of the binding that @ContributesAndroidInjector
generates for you, where the generated AndroidInjector.Factory
contains a @BindsInstance
binding 您在此处请求的类型。
这对您不起作用,因为您在 top-level 组件上安装的绑定中注入 MainActivity。这是一个问题,因为 AppComponent 将在 Activity 之前存在,并且随着 Android 重新创建 Activity 也将被替换:通过 @Component.Builder
传递实例是 不是解决这个问题的方法。
相反,将您的 FactoryVmModule::class
移动到 @ContributesAndroidInjector
生成的子组件中,您可以通过将其包含在 modules
attribute on @ContributesAndroidInjector
中来实现。 Dagger 将为每个 Activity 实例创建一个不同的子组件实例,因此您的 FactoryVmModule 将始终具有与 MainActivity.
的全新绑定
@Module
abstract class MainActivityModule {
@ContributesAndroidInjector(
modules = [ViewModelModule::class, FactoryVmModule::class]
)
abstract fun injectMainActivity(): MainActivity
}
我也把你的 ViewModelModule class 移到了那里;尽管如果它不依赖于属于 Activity 的任何内容,您可以将其留在 top-level 组件中,但您可能希望将它们放在一起。子组件中的绑定继承自应用程序,因此您可以从 Activity 的子组件中注入 AppComponent-level 绑定,但反之则不行。这意味着您将无法在 Activity 之外注入 VM 实例(此处为 TestVM),但如果它们依赖于 Activity,您无论如何都不想这样做:这些实例可能会过时并防止垃圾收集器回收您完成的 Activity 个实例。
MainActivity cannot be provided without an @Inject constructor or an @Provides-annotated method. This type supports members injection but cannot be implicitly provided.
我用的是dagger-android,我通过AndroidInjection.inject(this)注入了MainActivity,但是在Module中还是不可用。我准备了示例项目:https://github.com/deepsorrow/test_daggerIssu.git,文件如下:
FactoryVmModule:
@Module
class FactoryVmModule {
@Provides
@Named("TestVM")
fun provideTestVM(
activity: MainActivity, // <--- dagger can't inject this
viewModelFactory: ViewModelFactory
): TestVM =
ViewModelProvider(activity, viewModelFactory)[TestVM::class.java]
}
MainActivityModule:
@Module
abstract class MainActivityModule {
@ContributesAndroidInjector
abstract fun injectMainActivity(): MainActivity
}
MainActivity(使用 DaggerAppCompatActivity):
class MainActivity : DaggerAppCompatActivity() {
@Named("TestVM")
@Inject
lateinit var testVM: TestVM
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
测试应用程序:
class TestApplication : Application(), HasAndroidInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
override fun onCreate() {
super.onCreate()
DaggerAppComponent.create().inject(this)
}
override fun androidInjector() = dispatchingAndroidInjector
}
应用程序组件:
@Component(modules = [AndroidInjectionModule::class, MainActivityModule::class, ViewModelModule::class, FactoryVmModule::class])
interface AppComponent {
fun inject(application: TestApplication)
}
dagger.android does do this automatically: See the explicit version of the binding that @ContributesAndroidInjector
generates for you, where the generated AndroidInjector.Factory
contains a @BindsInstance
binding 您在此处请求的类型。
这对您不起作用,因为您在 top-level 组件上安装的绑定中注入 MainActivity。这是一个问题,因为 AppComponent 将在 Activity 之前存在,并且随着 Android 重新创建 Activity 也将被替换:通过 @Component.Builder
传递实例是 不是解决这个问题的方法。
相反,将您的 FactoryVmModule::class
移动到 @ContributesAndroidInjector
生成的子组件中,您可以通过将其包含在 modules
attribute on @ContributesAndroidInjector
中来实现。 Dagger 将为每个 Activity 实例创建一个不同的子组件实例,因此您的 FactoryVmModule 将始终具有与 MainActivity.
@Module
abstract class MainActivityModule {
@ContributesAndroidInjector(
modules = [ViewModelModule::class, FactoryVmModule::class]
)
abstract fun injectMainActivity(): MainActivity
}
我也把你的 ViewModelModule class 移到了那里;尽管如果它不依赖于属于 Activity 的任何内容,您可以将其留在 top-level 组件中,但您可能希望将它们放在一起。子组件中的绑定继承自应用程序,因此您可以从 Activity 的子组件中注入 AppComponent-level 绑定,但反之则不行。这意味着您将无法在 Activity 之外注入 VM 实例(此处为 TestVM),但如果它们依赖于 Activity,您无论如何都不想这样做:这些实例可能会过时并防止垃圾收集器回收您完成的 Activity 个实例。