Search code examples
javaandroiddagger-2dagger

Dagger2: how to inject retrofit module in presenter class


Dagger2 learning is still difficult and am trying to learn. Have setup a project using new dagger android to avoid injecting inside activity class. So far it's working but need to use retrofit injected in presenter class. Added retrofit module in AppComponent but apiService class method getting null when call from presenter class. Need to know how to inject properly.

AppComponent.java

@Singleton
@Component(modules = {
    /* Use AndroidInjectionModule.class if you're not using support library */
    AndroidSupportInjectionModule.class,
    AppModule.class,
    BuildersModule.class,
    RetrofitModule.class})
public interface AppComponent {

@Component.Builder
interface Builder {
    @BindsInstance
    Builder application(BaseApplication application);

    Builder retrofitModule(RetrofitModule retrofitModule);

    AppComponent build();
}

  void inject(BaseApplication app);
}

AppModule.java

@Module
class AppModule {

    @Provides
    Context provideContext(BaseApplication application) {
        return application.getApplicationContext();
    }
}

BuildersModule.java

@Module
public abstract class BuildersModule {

    @ContributesAndroidInjector(modules = {SplashViewModule.class, SplashModule.class})
    abstract SplashActivity bindSplashActivity();

    // Add bindings for other sub-components here
}

BaseApplication.java

public class BaseApplication extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();

        //configure timber for logging
        if (BuildConfig.DEBUG) {
            Timber.plant(new Timber.DebugTree());
        }

        DaggerAppComponent
                .builder()
                .application(this)
                .retrofitModule(new RetrofitModule())
                .build()
                .inject(this);
    }


    @Override
    public AndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}

RetrofitModule.java

@Module
public class RetrofitModule {

    //get retrofit instance
    @Singleton
    @Provides
    public UserAuthService getRestService() {

        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiConstants.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(getOkHttpClient())
                .build();

        return retrofit.create(UserAuthService.class);
    }
}

UserAuthService.java

public interface UserAuthService {

    @GET("v2/5be345062f00006b00ca22c4")
    Observable<Example> getExampleResponse();
}

SplashModule.java

@Module
public class SplashModule {

    @Provides
    SplashPresenter provideSplashPresenter(SplashView splashView) {
        return new SplashPresenter(splashView);
    }
}

SplashViewModule.java

@Module
public abstract class SplashViewModule {

    @Binds
    abstract SplashView provideSplashView(SplashActivity splashActivity);

}

SplashPresenter.java

class SplashPresenter extends BasePresenter<SplashView> {


    @Inject
    @Named(ValueConstants.MAIN_THREAD)
    Scheduler mMainThread;

    @Inject
    @Named(ValueConstants.NEW_THREAD)
    Scheduler mNewThread;

    @Inject
    UserAuthService userAuthService;

    SplashPresenter(SplashView view) {
        super(view);
    }

    //test purpose
    public void sayHello() {

        userAuthService.getExampleResponse()
                .observeOn(mMainThread)
                .subscribeOn(mNewThread)
                .subscribe(new Observer<Example>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Example example) {
                        Timber.d("example %s", example.toString());
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}

here "userAuthService.getExampleResponse()" getting null. I think presenter need to know about RetrofitModule injection. So I need to fix this and how?


Solution

  • I would add those dependencies to the constructor of SplashPresenter and add the @Inject annotation to it. Dagger2 supports constructor injection and all the dependencies you need are resolvable (and you can also get rid of SplashModule)

    class SplashPresenter extends BasePresenter<SplashView> {
    
       private Scheduler mMainThread;
    
       private Scheduler mNewThread;
    
       private UserAuthService userAuthService;
    
      @Inject
      SplashPresenter(SplashView view, UserAuthService userAuthService, @Named(ValueConstants.NEW_THREAD) Scheduler newThread,  @Named(ValueConstants.MAIN_THREAD) Scheduler mainThread) {
            super(view);
            this.userAuthService = userAuthService;
            mNewThread = newThread;
            mMainThread = mainThread;
      }