Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Android Architecture Components example GithubBrowserSample: ViewModelModule, ViewModel parameters

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?

like image 631
Vadims Savjolovs Avatar asked Sep 18 '17 11:09

Vadims Savjolovs


People also ask

What is ViewModel in Android architecture components?

Android Architecture Components provides the ViewModel helper class for the UI controller that is responsible for preparing data for the UI. ViewModel objects are automatically retained during configuration changes we will see that in the below example. Now let’s get into the code, Step 1: Add these dependencies in the build.gradle file

What is the new architecture component in Android framework?

Thanks to this, at Google I/O 2017 the Android Framework team introduced a new Architecture Component which deals this kind of rotation. The ViewModel class is designed to store and manage UI-related data in a conscious way. The ViewModel is able to live through the configuration changes.

What is the use of ViewModel in Android with Kotlin?

For more information, see Use Kotlin coroutines with Android Architecture Components. As your data grows more complex, you might choose to have a separate class just to load the data. The purpose of ViewModel is to encapsulate the data for a UI controller to let the data survive configuration changes.

Can a ViewModel have a constructor in Android?

If the ViewModel needs the Application context, for example to find a system service, it can extend the AndroidViewModel class and have a constructor that receives the Application in the constructor, since Application class extends Context. ViewModel objects are scoped to the Lifecycle passed to the ViewModelProvider when getting the ViewModel.


1 Answers

  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.

like image 194
David Medenjak Avatar answered Oct 11 '22 02:10

David Medenjak