javaandroidviewmodelandroid-viewmodel

Best way to retrieve the activity's ViewModel for second time


This is how the guides recommend retrieving the ViewModel of an activity for the first time, which normally happens inside the onCreate:

public class FooActivity extends AppCompatActivity {

    @Inject
    ViewModelProvider.Factory viewModelFactory;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...
        
        FooViewModel viewModel = new ViewModelProvider(this, viewModelFactory)
            .get(FooViewModel.class);
    }

}

Now that has to be a costly operation, since we are creating a new instance of ViewModelProvider. It is also somewhat verbose. What if I need the ViewModel again outside the onCreate?

I initially though of caching it in a private variable inside the activity, but can't that leak the ViewModel? E.g.:

public class FooActivity extends AppCompatActivity {
    FooViewModel viewModel;

    @Inject
    ViewModelProvider.Factory viewModelFactory;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...
        
        viewModel = new ViewModelProvider(this, viewModelFactory)
            .get(FooViewModel.class);
    }

    @Override
    protected void onStop() {
        //...
        
        viewModel.someMethod();
    }

}

Would this approach be safer if I manually set the viewModel variable to null in the onDestroy?

Another alternative approach would be to somehow retrieve the associated ViewModel from the activity. AppCompatActivity has a ViewModelStore, but calling getViewModelStore() returns an object where only a clear method is available.

So what is the recommended way of getting the associated ViewModel for a second time in a fragmentless activity?


Solution

  • I initially though of caching it in a private variable inside the activity, but can't that leak the ViewModel?

    Only if the activity itself is leaked. The lifetime of an activity's viewmodel is longer than the lifetime of the activity itself, since the viewmodel exists in part to survive configuration changes, which involves multiple instances of the activity sharing a viewmodel instance.

    Would this approach be safer if I manually set the viewModel variable to null in the onDestroy?

    Only if you leak your activities, which is a much bigger problem.

    So what is the recommended way of getting the associated ViewModel for a second time in a fragmentless activity?

    In Java, hold onto it in a field in the activity, as you have in your second code snippet.