Dagger2.11报错:无@Provides方法无法提供Toy,求排查解决
首先咱们来拆解一下你遇到的这个错误:
Error:(22, 8) error: [dagger.android.AndroidInjector.inject(T)] com.example.user.daggerapplication4.Models.Toy cannot be provided without an @Provides-annotated method.
com.example.user.daggerapplication4.Models.Toy is injected at com.example.user.daggerapplication4.ui.MainFragment.toy
com.example.user.daggerapplication4.ui.MainFragment is injected at com.example.user.daggerapplication4.ui.MainActivity.injectedFragment
com.example.user.daggerapplication4.ui.MainActivity is injected at dagger.android.AndroidInjector.inject(arg0)
A binding with matching key exists in component: com.example.user.daggerapplication4.ui.MainActivityModule_BindMainFragment.MainFragmentSubcomponent
错误核心原因
你在MainActivity中直接通过@Inject获取MainFragment实例,但**MainFragment依赖的Toy是在它专属的FragmentSubcomponent(由@ContributesAndroidInjector自动生成)中提供的,而MainActivity的Component并没有权限访问这个Subcomponent里的绑定**。
Dagger在尝试从MainActivity的Component中创建MainFragment时,找不到Toy的提供方法,所以抛出了这个错误——虽然你确实在MainFragmentModule里写了@Provides,但这个绑定只存在于Fragment自己的Subcomponent中,Activity的Component看不到它。
具体修复步骤
1. 移除Activity中对Fragment的直接注入
不要让MainActivity持有注入的MainFragment实例,而是在需要创建Fragment时直接new实例,Dagger会在Fragment依附到Activity的过程中自动完成注入。
修改MainActivity代码如下:
public class MainActivity extends DaggerAppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MainFragment mainFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame); if (mainFragment == null) { // 直接new Fragment实例,Dagger会自动处理注入 mainFragment = new MainFragment(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.contentFrame, mainFragment); transaction.commit(); } } }
2. 保留现有正确的配置(你已经做好了)
MainFragment的@Inject无参构造函数:这是Dagger能够自动注入Fragment的必要条件,你已经写对了。- 作用域与Module配置:
@FragmentScoped和@ActivityScoped的定义没问题,MainFragmentModule中@Provides @FragmentScoped Toy的配置也符合你的需求(每个Fragment实例拥有独立的Toy实例)。
修复后流程说明
当你完成上面的修改后,整个注入流程会变成这样:
- App启动,
AppComponent初始化完成 MainActivity被Dagger注入,进入onCreate生命周期- 创建
MainFragment实例并添加到Activity MainFragment触发onAttach生命周期,Dagger自动找到对应的MainFragmentSubcomponent(由@ContributesAndroidInjector生成)- Subcomponent通过
MainFragmentModule提供@FragmentScoped的Toy实例,完成对MainFragment的注入 - 点击按钮时,
toy.play()就能正常调用,输出日志
内容的提问来源于stack exchange,提问作者Eray Dogan

