Dagger 2.11 - A binding with matching key exists i

2019-02-15 11:42发布

问题:

I have a small scenario where I have this following structure where I'm trying to inject fragment manager in baseActivity Fragment but for some reason I'm running out of luck :(

@Singleton
@Component(modules = { AppModule.class,
        ActivityModule.class,
        AndroidSupportInjectionModule.class })
public interface AppComponent extends AndroidInjector<App> {

    @Override
    void inject(App application);

    @Component.Builder interface Builder {

        @BindsInstance
        AppComponent.Builder application(App application);

        AppComponent build();
    }
}

ActivityModule.class

@PerActivity
@ContributesAndroidInjector(modules = BaseActivityModule.class)
abstract BaseActivity baseActivity();

BaseActivityModule.class

static final String ACTIVITY_FRAGMENT_MANAGER = "ACTIVITY_FRAGMENT_MANAGER";

@PerActivity
@Named(ACTIVITY_FRAGMENT_MANAGER)
@Provides
static FragmentManager activityFragmentManager(BaseActivity activity) {
    return activity.getSupportFragmentManager();
}

BaseAcitivity.class

public abstract class BaseActivity extends DaggerAppCompatActivity {

    @Named(ACTIVITY_FRAGMENT_MANAGER)
    @Inject
    FragmentManager fragmentManager;
}

So even though i'm providing my fragment manager in BaseActivityModule.class dagger is throwing this following error. I even tried with just Activity instead of BaseActivity as my input parameter in BaseActivityModule. Even then I land up in this same issue. Not sure what exactly I'm screwing up. So any help is appreciated. Thanks in advance :)

Error:(17, 8) error: [dagger.android.AndroidInjector.inject(T)] @javax.inject.Named("ACTIVITY_FRAGMENT_MANAGER") android.support.v4.app.FragmentManager cannot be provided without an @Provides- or @Produces-annotated method.
@javax.inject.Named("ACTIVITY_FRAGMENT_MANAGER") android.support.v4.app.FragmentManager is injected at
com.abc.views.base.BaseActivity.fragmentManager
com.abc.views.def.ABCActivity is injected at
dagger.android.AndroidInjector.inject(arg0)
A binding with matching key exists in component: om.abc.views.base.BaseActivity_BaseActivity.BaseActivitySubcomponent

回答1:

"A binding with matching key exists in component" means that you have bound a dependency somewhere in your entire object graph but it cannot be reached from the subcomponent where it needs to be injected. Here is the javadoc:

Utility code that looks for bindings matching a key in all subcomponents in a binding graph so that a user is advised that a binding exists elsewhere when it is not found in the current subgraph. If a binding matching a key exists in a sub- or sibling component, that is often what the user actually wants to use.

For instance, assume you have two Activities, ActivityA and ActivityB. You generate subcomponents with @ContributesAndroidInjector and bind Foo in the ActivityA module but not the ActivityB module. If you request injection for Foo in ActivityB with @Inject Foo foo you will get that error message.

Forming subcomponents using @ContributesAndroidInjector on a base class like BaseActivity is probably not a good approach here. Like in the comment from David Medenjak, the subcomponent for the base class will be ignored and the subcomponent for the concrete class will perform injection on ABCActivity.

For now, you can fix your error by binding FragmentManager in the subcomponent for ABCActivity:

@PerActivity
@ContributesAndroidInjector(modules = BaseActivityModule.class)
abstract ABCActivity ABCActivity();


回答2:

Did you try provide without static ?

@Module(includes = {ViewModelModule.class})
public class AppModule {

@Provides
public PrefManager providePrefManager(Application app) {
    return PrefManager.getInstance(app);
}