Understanding Android Architecture Components example GithubBrowserSample: ViewModelModule, ViewModel parameters

2.2k views Asked by At

One of the most up to date samples covering Android Architecture Components is GithubBrowserSample provided by Google. I reviewed the code and a few questions arose:

  1. I have noticed that ViewModelModule is included in AppModule. It means that all the viewmodels are added to the DI graph. Why that is done in that way instead of having separate Module for each Activity/Fragment that would provide only needed ViewModel for specific Activity/Fragment?

  2. In this specific example, where viewmodels are instantiated using GithubViewModelFactory is there any way to pass a parameter to the specific ViewModel? Or the better solution would be to create a setter in ViewModel and set needed param via setter?

1

There are 1 answers

4
David Medenjak On BEST ANSWER
  1. [...] It means that all the viewmodels are added to the DI graph. Why that is done in that way instead of having separate Module for each Activity/Fragment [...]?

They are added to the DI graph, but they are not yet created. Instead they end up in a map of providers, as seen in the ViewModelFacory.

@Inject
public GithubViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) { }

So we now have a GithubViewModelFactory that has a list of providers and can create any ViewModel that was bound. Fragments and Activities can now just inject the factory and retrieve their ViewModel.

@Inject
ViewModelProvider.Factory viewModelFactory;

// ...later...
repoViewModel = ViewModelProviders.of(this, viewModelFactory).get(RepoViewModel.class);

As to the why...alternatively you could create a ViewModelProvider.Factory for every Activity / Fragment and register the implementation in every Module. This would be a lot of duplicated boilerplate code, though.

  1. In this specific example, where viewmodels are instantiated using GithubViewModelFactory is there any way to pass a parameter to the specific ViewModel? Or the better solution would be to create a setter in ViewModel and set needed param via setter?

It seems like all the ViewModels only depend on @Singleton objects—which is necessary, since they all get provided from the AppComponent. This means that there is no way to pass in "parameters" other than other @Singleton dependencies.

So, as you suggested, you'd either have to move the factory down into the Activity / Fragment component so that you can provide lower-scoped dependencies, or use a setter method.