Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
    }
}
like image 528
alexpfx Avatar asked Jul 03 '17 01:07

alexpfx


People also ask

How do you instantiate a ViewModel in Java?

To instantiate such basic viewmodel, create a ViewModelProvider with current activity/fragment reference and invoke get method with ViewModel's class.

Is Viewmodelproviders deprecated?

Public methods. This method is deprecated. Use the 'by viewModels()' Kotlin property delegate or ViewModelProvider , passing in the fragment. This method is deprecated.

How does a ViewModel work internally?

ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way.It is the main component in the MVVM architecture. ViewModel can be created with activity context or fragment context. When a ViewModel object is created, it is stored inside Activity OR FragmentManager.


1 Answers

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.

like image 138
Daniel Wilson Avatar answered Oct 04 '22 03:10

Daniel Wilson