如何用Dagger 2向动态创建的Fragment注入依赖?
首先,你遇到的这个IllegalArgumentException: No injector was found for ...错误,核心原因是你的宿主Activity没有实现Dagger Android所需的Fragment注入接口,导致Dagger无法找到合适的注入器来处理Fragment的依赖注入。下面是具体的修复步骤:
1. 修改MainActivity,实现HasSupportFragmentInjector
你的MainActivity目前只实现了Injectable,但要支持Fragment的注入,还需要实现HasSupportFragmentInjector,并注入DispatchingAndroidInjector<Fragment>来处理Fragment的注入请求。修改后的代码如下:
class MainActivity : AppCompatActivity(), Injectable, HasSupportFragmentInjector { @Inject lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment> private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item -> when (item.itemId) { R.id.navigation_home -> { message.setText(R.string.title_home) val weeklyFragment = WeeklyFragment.newInstance() openFragment(weeklyFragment) return@OnNavigationItemSelectedListener true } R.id.navigation_dashboard -> { message.setText(R.string.title_dashboard) return@OnNavigationItemSelectedListener true } R.id.navigation_notifications -> { message.setText(R.string.title_notifications) return@OnNavigationItemSelectedListener true } } false } override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) // 确保Activity先完成注入 super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) ButterKnife.bind(this) // 这里不再需要手动创建ViewModel,Fragment会自行注入Factory并获取 // val viewModel = ViewModelProviders.of(this, viewModelFactory).get(MyViewModel::class.java) navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener) } private fun openFragment(fragment: Fragment) { val transaction = supportFragmentManager.beginTransaction() transaction.replace(R.id.content_container, fragment) transaction.addToBackStack(null) transaction.commit() } override fun supportFragmentInjector(): AndroidInjector<Fragment> { return fragmentInjector } }
关键修改点:
- 实现
HasSupportFragmentInjector接口 - 注入
DispatchingAndroidInjector<Fragment> - 实现
supportFragmentInjector()方法返回注入器 - 在
onCreate开头调用AndroidInjection.inject(this)(确保Activity自身先完成注入)
2. 确保Dagger组件配置正确
检查你的AppComponent是否包含Dagger Android的核心模块,并且Activity的Module正确关联了Fragment的注入配置:
配置AppComponent
@Singleton @Component(modules = [ AndroidInjectionModule::class, AndroidSupportInjectionModule::class, MainActivityModule::class, ViewModelModule::class // 你的ViewModel相关模块 ]) interface AppComponent : AndroidInjector<MyApplication> { @Component.Factory abstract class Factory : AndroidInjector.Factory<MyApplication> }
配置MainActivityModule
让Activity的Module关联Fragment的注入器:
@Module abstract class MainActivityModule { @ContributesAndroidInjector(modules = [WeeklyFragmentModule::class]) abstract fun contributeMainActivity(): MainActivity }
配置WeeklyFragmentModule
创建Fragment专属的Module,提供ViewModel相关依赖:
@Module abstract class WeeklyFragmentModule { @Binds abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory @Binds @IntoMap @ViewModelKey(MyViewModel::class) abstract fun bindMyViewModel(viewModel: MyViewModel): ViewModel }
3. 确认Fragment的注入时机
你的WeeklyFragment已经实现了Injectable,DaggerViewModelHelper的AppInjector会在Fragment的onFragmentCreated生命周期回调中自动触发注入。如果仍有问题,可以手动在Fragment的onAttach方法中添加注入逻辑:
override fun onAttach(context: Context) { AndroidSupportInjection.inject(this) super.onAttach(context) }
错误原因解析
当你动态添加Fragment时,Dagger需要通过宿主Activity的supportFragmentInjector获取对应的注入器,而你的Activity之前未实现这个接口,导致Dagger找不到Fragment的注入入口,从而抛出"No injector was found"的错误。
按照上述步骤修改后,Dagger就能正确识别Fragment的注入器,自动将viewModelFactory注入到WeeklyFragment中,你也无需在MainActivity中手动声明ViewModel相关依赖。
内容的提问来源于stack exchange,提问作者grovemaster

