14

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
David Rawson
  • 20,912
  • 7
  • 88
  • 124
user3354265
  • 777
  • 1
  • 10
  • 26
  • 2
    How / what are you injecting? I'm guessing you're using other activities than a single BaseActivity. You'll have to provide the dependency from their components, the BaseActivity one gets ignored – David Medenjak Nov 04 '17 at 08:41

1 Answers1

29

"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.

Sibling component contains the binding that the user wants

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();
David Rawson
  • 20,912
  • 7
  • 88
  • 124
  • I see your point. what if i don't make a subcomponent for `BaseActivity` and use it as `@Module(includes = ABCActivityModule.class)` in my `ABCActivityModule.class`. Is it suppose to work ?? When i tried it it results me to same error. – user3354265 Nov 04 '17 at 14:10
  • @user3354265 can you try doing a clean/rebuild? If that doesn't work, can you post your `ABCActivityModule`? – David Rawson Nov 04 '17 at 22:43
  • Just did rebuild no change. BaseActivity Module is same as above. I'm still injecting in baseActivitity but I'm only including BaseActivityModule in my ABCActivityModule which looks like this. `@Module(includes = BaseActivityModule.class) public abstract class ABCActivityModule { @PerFragment @ContributesAndroidInjector abstract ABCFragment abcFragment(); }` Also, ABCActivity extends BaseActivity. So my main requirement is I want to use addFragment from my ABCActivity that 's y i want to inject fragmentManager in BaseActivity – user3354265 Nov 04 '17 at 23:00
  • @user3354265 are you sure you are providing the same flavour of `FragmentManager`? Perhaps you can carefully check the import statements. A common mistake is to use `android.Fragment.FragmentManager` in`android.support.v4.FragmentManager` somewhere else – David Rawson Nov 05 '17 at 19:21
  • I have already checked that i'm using support one. I think it doesn't like the injection in baseActivity not completely sure why?? – user3354265 Nov 05 '17 at 19:26
  • @user3354265 can you change the signature of your provides method to `activityFragmentManager(Activity activity)` ? – David Rawson Nov 05 '17 at 19:28
  • Since i'm using support one i tried using AppCompatActivity. same result :( – user3354265 Nov 05 '17 at 19:29
  • @user3354265 I don't think you will be able to easily get it to work with the base class. Maybe just live with the duplication for now and in a later stage in your project you can extract a base class – David Rawson Nov 05 '17 at 19:31
  • I really appreciate your help towards this. Right now i'm just using getSupportFragmentManager in base but it'll be nice if i can actually get it work. I made a [public repo](https://github.com/kdani41/Dagger2_11_support) for this scenario. If you ever get a chance please take a look. Thanks a lot I really appreciate your time :) – user3354265 Nov 05 '17 at 20:12
  • @user3354265 I did a pull request for your repo - would you mind accepting the answer (green tick)? – David Rawson Nov 05 '17 at 21:01