2

The dagger modules

@Module
public class NetModule {

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

    @Provides
    @Singleton
    OkHttpClient provideOkHttpClient() {
        OkHttpClient client = new OkHttpClient();
        return client;
    }

    @Provides
    @Singleton
    Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(BuildConfig.SERVER_BASE_URL)
                .client(okHttpClient)
                .build();
        return retrofit;
    }
}

@Module
public class AppModule{

    private Application application;

    public AppModule(Application application){
        this.application = application;
    }

    @Provides
    @Singleton
    Application provideApplication() {
        return application;
    }
}

@Module
public class ImageModule {

    @Provides
    @Singleton
    Picasso providePicasso(Application application, OkHttpClient client) {
        Picasso.Builder builder = new Picasso.Builder(application);
        builder.downloader(new OkHttp3Downloader(client));
        return builder.build();
    }

}

These are the components

@Singleton
@Component(modules={NetModule.class})
public interface NetComponent {

    void inject(MyFragment fragment);
}

@Singleton
@Component(modules={AppModule.class, ImageModule.class}, dependencies = {NetModule.class})
public interface ImageComponent {

    void inject(MyFragment fragment);
}

This is how I am registering the components

public class MyApp extends Application{

    @Override
    public void onCreate() {

        netComponent = DaggerNetComponent.builder()
                .netModule(new NetModule())
                .build();

        imageComponent = DaggerImageComponent.builder()
                .appModule(new appModule(this))
                .imageModule(new ImageModule())
                .build();

    }

}

And in the fragment

public class MyFragment extends Fragment {

   @Inject
   Retrofit retrofit;

   @Inject
   Picasso picasso;

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,   
     Bundle savedInstanceState) {

   ((MyApp)getActivity().getApplication()).getNetComponent().inject(this);

   ((MyApp)getActivity().getApplication()).getImageComponent().inject(this);
  ....

  }


}

I am getting compilation error as below

Error:(25, 10) error: com.squareup.picasso.Picasso cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.

What is the best way to achieve this in dagger 2?

Coder
  • 3,090
  • 8
  • 49
  • 85

1 Answers1

8

When Component A depends on type B, you're saying that every zero-arg getter on B will be available in A's graph. This means that you don't need to call inject separately on NetComponent, but you do need to expose OkHttpClient in NetComponent's definition.

This means NetComponent would look like this:

@Singleton
@Component(modules={NetModule.class})
public interface NetComponent {
    /** Exposes OkHttpClient. Used by components depending on NetComponent. */
    OkHttpClient getOkHttpClient();
}

And your onCreateView could look like this:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,   
    Bundle savedInstanceState) {

  ((MyApp)getActivity().getApplication()).getImageComponent().inject(this);

}

Internally, Dagger generates the DaggerNetComponent and DaggerImageComponent in two separate steps, but has ImageComponent call the new getOkHttpClient method. This also means that DaggerImageComponent can accept any implementation of NetComponent, not just the one Dagger generates.

Related resources:

Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251