androiddependency-injectiondagger-2subcomponent

MissingBinding object in MainComponent which is provided in module in subcompnent


I use "AppComponent" which has ActivityBuilderModule and ViewModelBuilderModule and SubComponent "NetworkComponent" which has NetworkModule which provide InterfaceRequest and I inject InterfaceRequest in Repository and inject Repository in ViewModel and the ViewModel is injected in Activity but I got this error:

[Dagger/MissingBinding] InterfaceRequests cannot be provided without an @Provides-annotated method.
public interface AppComponent {
  A binding with matching key exists in component: NetworkComponent
      InterfaceRequests is injected at
          ForYouRepository.interfaceRequests
      ForYouRepositoryis injected at
          NewsViewModel(newsRepository)
      NewsViewModel is injected at
          ViewModelBuilderModule.bindNewsViewModel(newsViewModel)
      java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
          ViewModelFactory(creators)
      tech.gplanet.shopx.di.ViewModelFactory is injected at
          tech.gplanet.shopx.ui.activities.NewsActivity.viewModelFactory
      tech.gplanet.shopx.ui.activities.NewsActivity

AppComponent:

@Singleton
@Component(modules = { AndroidInjectionModule.class, ActivityBuilderModule.class, ViewModelBuilderModule.class})
public interface AppComponent {

    void inject(MyApplication appClass);


    @Component.Builder
    interface Builder {

        @BindsInstance
        AppComponent.Builder context(Context context);
        
        AppComponent build();

    }
    NetworkComponent.Builder getNetworkComponentBuilder();
}

Network Component:

@Subcomponent(modules = {NetworkModule.class})
public interface NetworkComponent {

    void inject(RegisterationActivity registerationActivity);
    void inject(AuthenticationRepository repository);
    void inject(ForYouRepository repository);

    @Subcomponent.Builder
    interface Builder {

        @BindsInstance
        Builder customDeserializers(@Named("custom_deserializers") GeneralCustomDeserializerInterface[] deserializers);

        @BindsInstance
        @Nullable
        Builder baseUrl(@Named("base_url") String baseUrl);

        NetworkComponent build();
    }
}

Repository code:

  @Inject
    public InterfaceRequests interfaceRequests;


    @Inject
    public ForYouRepository(Context context) {
        NetworkComponent networkComponent = ((MyApplication)((Activity) context).getApplication()).getAppComponent()
                .getNetworkComponentBuilder()
                .baseUrl(Constants.BASE_URL)
                .customDeserializers(new GeneralCustomDeserializerInterface[]{})
                .build();

        networkComponent.inject(this);
    }

Network Module:

    @Provides
    public Gson provideGsonBuilder(@Named("custom_deserializers") GeneralCustomDeserializerInterface [] customDeserializersList) {

        GsonBuilder gsonBuilder = new GsonBuilder();

        if(customDeserializersList != null) {
            for(GeneralCustomDeserializerInterface customDeserializer : customDeserializersList)
                gsonBuilder.registerTypeAdapter(customDeserializer.getDeserializedClass(), customDeserializer);
        }

        return gsonBuilder.create();
    }

    @Provides
    public Retrofit provideRetrofitInstance(@Named("base_url") String baseURL,  Gson gson) {
        return new Retrofit.Builder()
                .baseUrl(baseURL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                //.callFactory(okHttpClient)
                .build();
    }

    @Provides
    public InterfaceRequests provideInterfaceRequests(Retrofit retrofit) {
        return retrofit.create(InterfaceRequests.class);
    }

Solution

  • I think you misunderstood subcomponent. Object in a subcomponent can't be used by the component. The relation is only in the opposite direction (subcomponent can use object from the main component)

    I think in your case you should use a network module in AppComponent