alexpfx
alexpfx

Reputation: 6700

Instantiate ViewModels directly, without making use of ViewModelProviders.of method

I have a ViewModel called RecipesViewModel. Usually, I instantiated it this way:

RecipesViewModel viewModel = ViewModelProviders.of(this, new ViewModelProvider.Factory() {
            @Override
            public <T extends ViewModel> T create(Class<T> modelClass) {
                return (T) new RecipesViewModel(recipesRepository);
            }
        }).get(RecipesViewModel.class);

But now I'm using dagger2 and so I put a @Inject annotation on the constructor of this ViewModel, so I'm able to inject it directly in my fragment, using field injector.

My question is: do I lose something starting the viewmodel this way instead of ViewModelProviders.of way? My ViewModel is already Scoped, so only one instance is create in context.

Other option is to move only the factory instantiation to a dagger2 module, but if there is no problem I prefer the first aproach.

-- EDIT --

Reading the documentation android.arch.lifecycle.ViewModel, I'm a little more afraid. Whe use ViewModelProviders.of to provide a Scope (fragment or activity). If I instantiate it directly what will be the Scope?

ViewModel is a class that is responsible for preparing and managing the data for an Activity or a Fragment. It also handles the communication of the Activity / Fragment with the rest of the application (e.g. calling the business logic classes).

A ViewModel is always created in association with a scope (an fragment or an activity) and will be retained as long as the scope is alive. E.g. if it is an Activity, until it is finished.

In other words, this means that a ViewModel will not be destroyed if its owner is destroyed for a configuration change (e.g. rotation). The new instance of the owner will just re-connected to the existing ViewModel.

-- /EDIT --

The RecipesViewModel code is showing below:

@PerActivity
public class RecipesViewModel extends ViewModel {
    private static final String TAG = "RecipesViewModel";
    private final RecipesRepository recipesRepository;

    private LiveData<List<Recipe>> recipes = null;

    @Inject
    public RecipesViewModel(RecipesRepository recipesRepository) {
        this.recipesRepository = recipesRepository;
    }

    public final void loadAll() {
        recipes = recipesRepository.getRecipes();
    }

    public LiveData<List<Recipe>> getRecipes() {
        return recipes;
    }
}

Upvotes: 6

Views: 2676

Answers (1)

Daniel Wilson
Daniel Wilson

Reputation: 19824

For me right now (and I need to research this), but injecting a view model instead of using the ViewModelProviders functionality means you lose some easy activity-fragment communication.

For example from the docs they provide an example of an activity hosting 2 fragments. If one fragment needs to talk to another, the previous method was to maintain an interface via the activity who also had to take care of the lifecycle of that interface. Instead now you can just fetch it from the the ViewModelProviders 'repo' whenever you need.

Upvotes: 2

Related Questions