-1

I'm following the new Dagger2 support for android to implement a movies list sample application and below is my use case.

  • Activity Holds a fragment used to load list of movies
  • Fragment uses a presenter to hit an api using retrofit
  • Presenter has a dependency to the API interface class which contains Observale for the movies

I'm using @Inject inside the presenter for the ApiService interface but i got an error that i cannot use @Inject field without declaring provide annotation and below is my code

Main App component enter image description here

My Movies module enter image description here

My Movies Contract enter image description here

My Presenter enter image description here

and finally the api service interface

enter image description here

So how can i provide the service interface to MoviesModule in order to work properly inside the presenter

The error is

Error:(22, 8) error: [dagger.android.AndroidInjector.inject(T)] sampler.dagger.com.movieslist.data.MoviesApiService cannot be provided without an @Provides-annotated method.
sampler.dagger.com.movieslist.data.MoviesApiService is injected at
sampler.dagger.com.movieslist.movies.MoviePresenter.mApiService
sampler.dagger.com.movieslist.movies.MoviePresenter is injected at
sampler.dagger.com.movieslist.movies.MoviesModule.moviesPresenter(presenter)
sampler.dagger.com.movieslist.movies.MoviesContract.Presenter is injected at
sampler.dagger.com.movieslist.movies.MoviesFragment.mPresenter
dagger.Lazy<sampler.dagger.com.movieslist.movies.MoviesFragment> is injected at
sampler.dagger.com.movieslist.movies.MainActivity.mMoviesFragmentsProvider
sampler.dagger.com.movieslist.movies.MainActivity is injected at
dagger.android.AndroidInjector.inject(arg0)
user101530
  • 87
  • 12
  • 4
    Please include the _code_ and not screenshots of it as well as the full error message. Please have a look here on [how to fix _cannot be provided_](https://stackoverflow.com/q/44912080/1837367) – David Medenjak Mar 03 '18 at 21:04
  • @DavidMedenjak just added the full error – user101530 Mar 03 '18 at 21:13
  • Please have a look at the linked question as it includes all the details about your error and possible solutions. You will have to add `MoviesApiService` to one of your modules and provide it. – David Medenjak Mar 03 '18 at 22:32

2 Answers2

1

One solution could be:

@Module
public class APIModule {

    @Provides
    @Singleton
    Retrofit provideRetrofit(Gson gson) {
        OkHttpClient client = new OkHttpClient.Builder().build();
        return new Retrofit.Builder()
            .baseUrl("https://stackoverflow.com/")
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(client)
            .build();
    }

    @Provides
    @Singleton
    Gson provideGson() {
        return new GsonBuilder().create();
    }

    @Provides
    @Singleton
    MoviesApiService provideMoviesApiService(Retrofit retrofit) {
        return retrofit.create(MoviesApiService.class);
    }
}

In your MoviePresenter its better to use constructor injection than field injection:

private MoviesApiService mApiService;

@Inject
public MoviePresenter(MoviesApiService apiService) {
    mApiService = apiService;
}
daniel.keresztes
  • 875
  • 2
  • 15
  • 25
-2

MoviApiService is an interface, you cannot inject an interface. You need to create a provides method to provide the retrofit service.

MoviApiService providesMoviApiService(Retrofit retrofit) { retrofit.create(MoviApiService.class); }

cherif
  • 1,164
  • 1
  • 11
  • 16
  • Yes you can `@Binds`? i.e. in a Module : `@Binds static MovieApiService provideMyApi(Retrofit retrofit) { return retrofit.create(MoviApiService.class); };`. Although OP should be using constructor injection. – Mark Mar 03 '18 at 21:36
  • That was my point, you are creating the retrofit service, not injecting a "plain interface" – cherif Mar 03 '18 at 22:34
  • @MarkKeen Binds needs the method to be abstract – user101530 Mar 03 '18 at 22:34
  • '@binds' needs to be abstract, '@provides' doesn't need it – cherif Mar 03 '18 at 22:41
  • @user101530 thanks for the correction `@Provides static MovieApiService provideMyApi(Retrofit retrofit) { return retrofit.create(MoviApiService.class); };` At cherif - you can still inject an interface? The return type is fine? Your answer is still fundamentally incorrect. – Mark Mar 03 '18 at 22:53