3

MVVM + Dagger2

I'm very new to Dagger. I've gone through many sample project and created this.

What i want to know is using the below code, how to send data to specific ViewModels. I know how to do it by creating specific ViewModelProvider.Factory. But how do i do it when i have a generic Factory class.

ViewModelModule.Class

@Module
public class ViewModelModule {

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {
    Class<? extends ViewModel> value();
}

@Provides
ViewModelFactory viewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> providerMap) {
    return new ViewModelFactory(providerMap);
}

@Provides
@IntoMap
@ViewModelKey(MyViewModel1.class)
ViewModel viewModel1(FetchDataUseCase1 fetchDataUseCase1) {
    return new MyViewModel1(fetchDataUseCase1);
}

@Provides
@IntoMap
@ViewModelKey(MyViewModel2.class)
ViewModel viewModel2(FetchDataUseCase2 fetchDataUseCase2) {
    return new MyViewModel2(fetchDataUseCase2);
}
}

ViewModelFactory.class

@Singleton
public class ViewModelFactory implements ViewModelProvider.Factory {

private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;

@Inject
public ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
    this.creators = creators;
}

@NonNull
@SuppressWarnings("unchecked")
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
    Provider<? extends ViewModel> creator = creators.get(modelClass);
    if (creator == null) {
        for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
            if (modelClass.isAssignableFrom(entry.getKey())) {
                creator = entry.getValue();
                break;
            }
        }
    }
    if (creator == null) {
        throw new IllegalArgumentException("unknown model class " + modelClass);
    }
    try {
        return (T) creator.get();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
}

TIA

Shahal
  • 1,008
  • 1
  • 11
  • 29
  • 1
    1. Make the `ViewModelModule` an abstract class and [define abstract functions](https://github.com/chrisbanes/tivi/blob/master/app/src/main/java/app/tivi/showdetails/ShowDetailsBuilder.kt#L42) for individual viewmodels. Dagger will take care of injecting the constructor arguments. 2. If you want to inject some dynamic data into the constructor of viewmodel from fragment, then consider using [`AssistedInject`](https://github.com/square/AssistedInject). Example: [1](https://github.com/chrisbanes/tivi/blob/master/ui-discover/src/main/java/app/tivi/home/discover/DiscoverViewModel.kt) line 137 & 44 – denvercoder9 Sep 18 '19 at 04:27

0 Answers0