I am stuck with completing Dagger 2 Retrofit2 implementation using mvp where my app is making calls to two distinct apis, in respective fragments. I have defined qualifier annotations to bind an instance of Retrofit for each Api call as below

@Qualifier
@Retention(RUNTIME)
public @interface FirstApi{}

@Qualifier
@Retention(RUNTIME)
public @interface SecondApi{}

Binding each Retrofit in the ApplicationModule

public class ApplicationModule {

private String mBaseUrlFirstApi;
private String mBaseUrlSecondApi;
private Context mContext;

public ApplicationModule(Context context) {
        mContext = context;
    }

...
@Provides 
@FirstApi Retrofit provideFirstApiRetrofit(…) {…}
@Provides
@SecondApi Retrofit provideSecondApiRetrofit(…) {…}

....
}

ApplicationComponent

@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {

    Retrofit exposeRetrofit();

    Context exposeContext();
}

Scope

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {
}

Providing ApiService

@Module
public class MyModule {

    @PerActivity
    @Provides
    MyAPIService myApiService(Retrofit retrofit) {
        return retrofit.create(MyAPIService.class);
    }
}

Dagger Injector class

@PerActivity
@Component(modules = MyModule.class, dependencies = ApplicationComponent.class)
public interface MyComponent {

    void inject(Fragment1 fragment1);
    void inject(Fragment2 fragment2);
    // void inject(Fragment3 fragment3);
}

In the Application class, for a single retrofit Api call, i know to do:

public class MyApplication extends Application {

    private ApplicationComponent mApplicationComponent;

{...}
 private void initializeApplicationComponents() {
        mApplicationComponent = DaggerApplicationComponent
                .builder()
                .applicationModule(new ApplicationModule(this, "http://api1"))
                .build();
    }

{...}

public ApplicationComponent getApplicationComponent() {
        return mApplicationComponent;
    }

}

But for multiple url api calls, this does not work

public class MyApplication extends Application {

    private ApplicationComponent mApplicationComponent;

{...}
 private void initializeApplicationComponents() {
        mApplicationComponent = DaggerApplicationComponent
                .builder()
                .applicationModule(new ApplicationModule(this, "http://api1"))
                .applicationModule(new ApplicationModule(this, "http://api2"))
                .build();
    }

{...}

public ApplicationComponent getApplicationComponent() {
        return mApplicationComponent;
    }
}

Neither does this

public class MyApplication extends Application {

    private ApplicationComponent mApplicationComponent;

{...}
 private void initializeApplicationComponents() {
        mApplicationComponent = DaggerApplicationComponentApi1
                .builder()
                .applicationModule(new ApplicationModule(this, "http://api1"))
                .build();

        mApplicationComponent = DaggerApplicationComponentApi2
                .builder()
                .applicationModule(new ApplicationModule(this, "http://api2"))
                .build();
    }

{...}

public ApplicationComponent getApplicationComponent() {
        return mApplicationComponent;
    }

}

Resolving dagger dependency in each fragment is done like so

protected resolveDaggerDependency() {
    DaggerFragmentComponent
            .builder()
            .applicationComponent(getApplicationComponent)
            .myModule(new MyModule.class)
            .build.inject(this);
}

BaseFragment class has

public abstract class BaseFragment extends Fragment {

{...}
{...}
{...}

@CallSuper
protected void onViewReady(Bundle savedInstanceState, Intent intent) {
    resolveDaggerDependency(); // to be used by child fragments

protected ApplicationComponent getApplicationComponent() {
    return ((MyApplication)getActivity().getApplication()).getApplicationComponent;
}

}
1

There are 1 best solutions below

0
On

Before you call

mApplicationComponent = DaggerApplicationComponent
                .builder()
                .applicationModule(new ApplicationModule(this, "http://api1"))
                .applicationModule(new ApplicationModule(this, "http://api2"))
                .build();

Make the project and use code completion to see what Android Studio tells you is available for the component builder. My hunch is that your application module's constructor doesn't take both a context and a string. Once you change the constructor, to take say

ApplicationModule(Context context, String url1, String url2) {...}

then all you'd need to do is to change your injection code to delete the second line of .applicationModule and change the first line to match the new constructor, i.e.:

mApplicationComponent = DaggerApplicationComponent
                .builder()
                .applicationModule(new ApplicationModule(this, "http://api1", "http://api2"))
                .build();