0

I have read the following articles but I don't know what I am doing wrong.

  1. Dagger AndroidInjector cannot be provided without an @Provides-annotated method

  2. <android.arch.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method

Stack trace

error: [Dagger/MissingBinding] androidx.lifecycle.ViewModelProvider.Factory cannot be provided without an @Provides-annotated method.
A binding with matching key exists in component: com.mycompany.mobile.dagger.AppModule_ContributeSettingsActivityInjector.SettingsActivitySubcomponent
A binding with matching key exists in component: com.mycompany.mobile.settings.dagger.SettingsActivityModule_ContributeSignInPreferencesFragment.AuthenticationPreferencesFragmentSubcomponent
androidx.lifecycle.ViewModelProvider.Factory is injected at
com.mycompany.mobile.notifications.PushJobIntentService.viewModelProviderFactory
com.mycompany.mobile.notifications.PushJobIntentService is injected at
dagger.android.AndroidInjector.inject(T) [com.mycompany.mobile.dagger.AppComponent → com.mycompany.mobile.dagger.AppModule_ContributePushJobIntentServiceInjector.PushJobIntentServiceSubcomponent]

ViewModelProvider.Factory implementation

public class InjectableViewModelProviderFactory implements ViewModelProvider.Factory
{
    private final Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModelMap;

    @Inject
    InjectableViewModelProviderFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModelMap)
    {
        this.viewModelMap = viewModelMap;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass)
    {
        final Provider<ViewModel> viewModelProvider = viewModelMap.get(modelClass);
        if (viewModelProvider != null)
        {
            final ViewModel viewModel = viewModelProvider.get();
            if (modelClass.isInstance(viewModel))
            {
                final T viewModelAsModelClass = modelClass.cast(viewModel);
                if (viewModelAsModelClass != null)
                    return viewModelAsModelClass;
            }
        }
        throw new IllegalStateException(String.format("Could not find view model provider for %1$s",
            modelClass.getSimpleName()));
    }
}

Module # 1

@Module
public abstract class ViewModelInjectionModule
{
    @Binds
    abstract ViewModelProvider.Factory bindViewModelProviderFactory(InjectableViewModelProviderFactory factory);

    @Multibinds
    abstract Map<Class<? extends ViewModel>, ViewModel> provideViewModelProviderMap();
}

Module# 2

There are multiple such modules that inject keys into other modules.

@Module(includes=ViewModelInjectionModule.class)
public abstract SettingsModule {

@Binds
    @IntoMap
    @ViewModelKey(NotificationsViewModel.class)
    abstract ViewModel bindNotificationsViewModel(NotificationsViewModel viewModel);

    @Binds
    @IntoMap
    @ViewModelKey(DcsViewModel.class)
    abstract ViewModel bindDcsViewModel(DcsViewModel viewModel);
}

The ViewModel.Factory instance is injected in an instance of IntentService.

public class PushJobIntentService extends IntentService
{

    @Inject
    ViewModelProvider.Factory viewModelProviderFactory;

    @Override
    protected void onHandleWork(@NonNull Intent intent)
    {

        ... Run an intent service . . . 
    }
}

AppModule

@Module(includes = {
    AnalyticsAppModule.class,
    AppUpgradeModule.class,
    AndroidSupportInjectionModule.class,
    AppDcsModule.class
})
public abstract class AppModule
{

    @ActivityScope
    @ContributesAndroidInjector(modules = {SettingsModule.class})
    abstract SettingsActivity contributeSettingsActivityInjector();
}

AppComponent

@Singleton
@Component(
    modules = {
        AppModule.class,
        .. . Other modules
    })
public interface AppComponent {
    @NonNull
DispatchingAndroidInjector<Activity> getDispatchingActivityInjector();

   . . . Other Activity Injectors. . . 
}

Any suggestion would be appreciated.

Krish
  • 63
  • 6
  • 1
    As i have used dagger in two of my project ,i use @ Provides and @ Singleton for singleton instance . You may check this link : https://android.jlelse.eu/7-steps-to-implement-dagger-2-in-android-dabc16715a3a – Mini Chip Jun 06 '19 at 11:55
  • I think this ViewModelProvider.Factory implementation is a mistake and people should be using this approach: https://youtu.be/9fn5s8_CYJI?t=1720 – EpicPandaForce Jun 06 '19 at 12:01
  • Are you adding the module with the `@Binds` method (or the settings module which includes it) to your `AppComponent`? Dagger can't find the binding, hence it complains. See [here](https://stackoverflow.com/q/44912080/1837367) for general info on how to read the error – David Medenjak Jun 06 '19 at 12:11
  • @DavidMedenjak I am trying to bind the key-value that can be injected into the map that is in turn injected into the ViewModelFactory implementation. – Krish Jun 06 '19 at 18:07
  • @EpicPandaForce I am afraid that I don't understand the Kotlin examples. – Krish Jun 06 '19 at 18:09
  • @Krish Look at your error. Dagger can't find your factory: `ViewModelProvider.Factory cannot be provided`. You don't show if, how, or where you add the binding. Please check the linked question to see how to read the error and please update your question to include all of the relevant information (how you add your binding to `AppComponent`) if you need further guidance – David Medenjak Jun 06 '19 at 18:22
  • @DavidMedenjak I have updated the post. – Krish Jun 06 '19 at 18:53
  • @Krish You're still not showing how/where you add `SettingsModule`. I see `ViewModelProvider.Factory > ViewModelInjectionModule > SettingsModule > [???] > AppComponent` – David Medenjak Jun 06 '19 at 18:59
  • @DavidMedenjak Done – Krish Jun 06 '19 at 22:38
  • @Krish You're adding the binding to `SettingsActivity`, but not to `AppComponent`. As such Dagger can't find it when trying to inject `PushJobIntentService`. Please [read here](https://stackoverflow.com/q/44912080/1837367) for more general information on how you can read and fix your problem. – David Medenjak Jun 07 '19 at 06:57

0 Answers0