androiddependency-injectionmvpdagger-2

Dagger 2 can not resolve symbol 'DaggerAppComponent'


I'm trying to create a simple app with retrofit 2, dagger 2 and MVP, but I struggle with dependencies, actualy, this is the error I get after i try to rebuild the project Error:Execution failed for task ':app:compileDebugJavaWithJavac'.

java.lang.StackOverflowError

and also in App class where I provide AppComponent: can not resolve symbol 'DaggerAppComponent'

I'll try to show you what my project looks like so someone can see the problem, First one is my AppModule which includes PresentationModule.class

@Module(includes = PresentationModule.class)
public class AppModule {
    private App app;

    public AppModule(App app) {
        this.app = app;
    }

    @Provides
    @Singleton
    public App provideApp() {
        return app;
    }
}

Presentation Module looks like this:

@Module(includes = InteractorModule.class)
public class PresentationModule {

    @Provides
    JokePresenter providePresenter(JokeInteractor jokeInteractor) {
        return new JokePresenterImpl(jokeInteractor);
    }
}

And InteractorModule:

@Module(includes = {NetworkModule.class, PresentationModule.class})
public class InteractorModule {

    @Provides
    JokeInteractor provideJokeInteractor(RetrofitService service, JokePresenter presenter) {
        return new JokeInteractorImpl(service, presenter);
    }
}

This is JokePresenter that has a reference to view and interactor:

public class JokePresenterImpl implements JokePresenter {

    private JokeView mJokeView;
    private List<String> mData = new ArrayList<>();
    private String mJoke;
    private JokeInteractor jokeInteractor;

    public JokePresenterImpl(JokeInteractor jokeInteractor) {
        this.jokeInteractor = jokeInteractor;
    }

    @Override
    public void setView(JokeView view) {
        this.mJokeView = view;
    }

    @Override
    public void getRandomJoke() {
        mJokeView.showProgress();
        jokeInteractor.getRandomJoke();
    }
}

And JokeInteractor that has a RetrofitService and JokePresenter references:

public class JokeInteractorImpl implements JokeInteractor {

    private RetrofitService retrofitService;
    private JokePresenter presenter;

    public JokeInteractorImpl(RetrofitService service, JokePresenter presenter) {
        this.retrofitService = service;
        this.presenter = presenter;
    }

    @Override
    public void getRandomJoke() {
        retrofitService.getRandomJoke()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<RandomJokeResponse>() {
                    @Override
                    public void onCompleted() {
                        presenter.onRandomJokeCompleted();
                    }

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

                    @Override
                    public void onNext(RandomJokeResponse randomJokeResponse) {
                        presenter.onNextRandomJoke(randomJokeResponse);
                    }
                });
    }

Gradle dependencies:

  apt 'com.google.dagger:dagger-compiler:2.7'
  compile 'com.google.dagger:dagger:2.7'
  provided 'javax.annotation:jsr250-api:1.0'

    //retrofit
  compile 'com.squareup.retrofit2:retrofit:2.1.0'
  compile 'com.squareup.okhttp:okhttp:2.5.0'
  compile 'com.squareup.retrofit2:converter-gson:2.1.0'
  compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

  //rx java
  compile 'io.reactivex:rxjava:1.1.6'
  compile 'io.reactivex:rxandroid:1.2.1'

 //dagger2
  compile 'com.google.dagger:dagger:2.0'
  provided 'org.glassfish:javax.annotation:10.0-b28'

Can someone see the problem here?


Solution

  • Look at the implementation of:

    @Module(includes = InteractorModule.class)
    public class PresentationModule
    

    and

    @Module(includes = {NetworkModule.class, PresentationModule.class})
    public class InteractorModule
    

    You have a cyclic dependency. You need to rethink your design. I propose to decouple Interactor from Presenter.

    A simple solution:

    Change getRandomJoke() implementation to return Observable and subscribe to it inside Presenter. And remove presenter reference from Interactor.

    Interactor:

    public class JokeInteractorImpl implements JokeInteractor {
    
        private RetrofitService retrofitService;
    
        public JokeInteractorImpl(RetrofitService service) {
            this.retrofitService = service;
        }
    
        @Override
        public Observable getRandomJoke() {
            return retrofitService.getRandomJoke()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
        }
    }
    

    Presenter:

    @Override
    public void getRandomJoke() {
        mJokeView.showProgress();
        jokeInteractor.getRandomJoke()
              .subscribe(new Observer<RandomJokeResponse>() {
                    @Override
                    public void onCompleted() {
                        onRandomJokeCompleted();
                    }
    
                    @Override
                    public void onError(Throwable e) {
                        onError(e.getMessage());
                    }
    
                    @Override
                    public void onNext(RandomJokeResponse randomJokeResponse) {
                        onNextRandomJoke(randomJokeResponse);
                    }
                });
    }