这是我的场景:
- 我希望我所有的 Activity 都继承自
BaseActivity
在
BaseActivity
中,我想注入(inject)Navigator
(它帮助我管理Fragments
后台堆栈并在 Activity 之间导航) :abstract class BaseActivity : DaggerAppCompatActivity() { @Inject lateinit var navigator: Navigator @Inject lateinit var prefs: SharedPreferences // injected via AppModule.kt, see below. }
Navigator
类在其构造函数中需要一个FragmentManager
:class Navigator @Inject constructor( val fragmentManager: FragmentManager) { // class body }
我想从
BaseActivityModule
中的BaseActivity
对象提供FragmentManager
:@Module class BaseActivityModule { @PerActivity @Provides fun provideFragmentManager(baseActivity: BaseActivity): FragmentManager { return baseActivity.supportFragmentManager } }
这是我的其余组件和模块:
AppComponent.kt
@Singleton @Component(modules = [ AndroidSupportInjectionModule::class, AppModule::class, ActivityBindingModule::class]) interface AppComponent { @Component.Builder interface Builder { @BindsInstance fun application(application: Application): Builder fun build(): AppComponent } fun inject(app: AndroidApplication) }
AppModule.kt
@Module class AppModule { @Singleton @Provides fun providesPrefs(application: Application): SharedPreferences { return application.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE) } }
ActivityBindingModule.kt
@Module abstract class ActivityBindingModule { @ContributesAndroidInjector abstract fun bindMainActivity(): MainActivity @ContributesAndroidInjector(modules = [(BaseActivityModule::class)]) abstract fun bindBaseActivity(): BaseActivity }
BaseActivityModule.kt
@Module class BaseActivityModule { @Provides fun provideFragmentManager(baseActivity: BaseActivity): FragmentManager { return baseActivity.supportFragmentManager } }
这是编译错误信息:
Error: [dagger.android.AndroidInjector.inject(T)]
android.support.v4.app.FragmentManager cannot be provided
without an @Provides- or @Produces-annotated method.
Error:A binding with matching key exists in component:
com.myapp.ActivityBindingModule_BindBaseActivity.BaseActivitySubcomponent
最佳答案
问题在于您假设您需要在某个时候注入(inject) BaseActivity
...
@Module
abstract class ActivityBindingModule {
@ContributesAndroidInjector
abstract fun bindMainActivity(): MainActivity
// ...that's not really how it works... :/
@ContributesAndroidInjector(modules = [(BaseActivityModule::class)])
abstract fun bindBaseActivity(): BaseActivity
}
使用上面的代码,你最终会得到一些组件来注入(inject) MainActivity
,一些组件来注入(inject) BaseActivity
,但两者都不能注入(inject)。您收到的错误是因为 MainActivity
无法提供它需要在其父级 BaseActivity
中注入(inject)的 FragmentManager
。它缺少这样做的模块。您仅将 BaseActivityModule
添加到您的其他组件,而 MainActivityComponent 实际上无权访问该组件——因此出现无法提供错误。
Dagger 总是需要注入(inject)整个对象。没有部分注入(inject),也没有一次从多个组件注入(inject)。如果单个组件不能提供所有 它需要的依赖项,您将得到一个错误。您的 fun bindBaseActivity(): BaseActivity
没有用,因为您永远不会使用 BaseActivity
,而只会使用 MainActivity
或它的其他子类。 那些组件还需要能够提供 BaseActivity 的依赖项。
如果您想在 BaseActivity 中注入(inject)依赖项,您需要添加一个提供必要绑定(bind)的模块。您的代码最终应如下所示:
@Module
abstract class ActivityBindingModule {
@ContributesAndroidInjector(modules = [BaseActivityModule::class, MainActivityModule::class])
abstract fun bindMainActivity(): MainActivity
// no BaseActivity component necessary
}
@Module
abstract class MainActivityModule {
@Binds
abstract fun bindBaseActivity(activity: MainActivity) : BaseActivity
}
这会做以下事情:
- 它将
BaseActivityModule
添加到 MainActivityComponent,这样您的基础依赖项就可以由该组件提供,并且可以注入(inject)MainActivity
- 它将另一个模块中的
MainActivity
绑定(bind)为您的BaseActivity
,这样您就可以在您的模块中使用它,而不必为您拥有的每个 Activity 都绑定(bind)一个 FragmentManager
虽然您可以重用 BaseActivityModule
并将其添加到所有 Activity 实现中,但您必须添加一个模块以将 Activity 绑定(bind)为 BaseActivity
你的 Activity 。
可能有更优化的方法,但这是注入(inject)子类的基本要求。
关于android - 如何使用 dagger.android 在 BaseActivity 中 @Inject 成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48533899/