252

With the introduction of the Android Architecture Components library, several new classes were introduced, including AndroidViewModel and ViewModel. However, I'm having trouble figuring out the difference between these two classes. The documentation succinctly describes AndroidViewModel as follows:

Application context aware ViewModel

I appreciate the brevity, but what exactly does this imply? When should we choose to use AndroidViewModel over ViewModel and vice-versa?

AdamHurwitz
  • 9,758
  • 10
  • 72
  • 134
cascal
  • 2,943
  • 2
  • 17
  • 19

4 Answers4

314

AndroidViewModel provides Application context

If you need to use context inside your Viewmodel you should use AndroidViewModel (AVM), because it contains the application context. To retrieve the context call getApplication(), otherwise use the regular ViewModel (VM).

AndroidViewModel has application context. We all know having static context instance is evil as it can cause memory leaks!! However, having static Application instance is not as bad as you might think because there is only one Application instance in the running application.

Therefore, using and having Application instance in a specific class is not a problem in general. But, if an Application instance references them, it is a problem because of the reference cycle problem.

See Also about Application Instance

AndroidViewModel Problematic for unit tests

AVM provides application context which is problematic for unit testing. Unit tests should not deal with any of the Android lifecycle, such as context.

AdamHurwitz
  • 9,758
  • 10
  • 72
  • 134
Alex
  • 9,102
  • 3
  • 31
  • 35
  • 50
    Why not always use AndroidViewModel then? you might later need the context even if you don't need it now. Is there any downside to that? – SamAko Nov 16 '17 at 17:20
  • 26
    @T.Rex If you look at the code, it extends `ViewModel` with just a field pointing to Application. If I don't need it, I don't like having a mandatory constructor with `Application` parameter (which `AndroidViewModel` requires) and rather just use `ViewModel`. When I need a context in the future, I can easily change it then. – Boy Nov 22 '17 at 14:31
  • 4
    Use `ViewModel` when you want to use it with Fragment or to share `ViewModel` between different fragments of same Activity. – codelearner Jan 27 '18 at 15:38
  • 25
    @T.Rex wouldn't using `AndroidViewModel` - being `Context`-dependent - make it impossible to test it in a regular unit test, leaving only instrumentation tests as a possibility? I haven't toyed with it myself (yet), it's just a thought – Konrad Morawski Feb 15 '18 at 18:32
  • @KonradMorawski that sounds right. Probably not worth the trouble – SamAko Feb 21 '18 at 22:40
  • When ViewModel or AndroidViewModel will be destroyed? Suppose i am executing AsyncTask in that model and i destroy app by swiping app from recent apps menu, What will happen with application context, ViewModel, AndroidViewModel and AsyncTask? – Mitul Varmora Jul 10 '18 at 05:41
  • can I get the instance of simpleviewmodel through ViewModelProviders.of(this);?? – Urvish rana Jul 30 '18 at 10:10
  • So lets say I want to load data from MediaStore (Content Provider, requires Context) and I want to display that data in Fragments. I need AndroidViewModel to load but ViewModel to display? – Chapz Sep 18 '18 at 19:33
  • 3
    AndroidViewModel and ViewModel is the same, the only difference is that AndroidViewModel contains the application context. You can use use ViewModel and to pass context to ViewModel to function that loading data from MediaStore, or use AndroidViewModel with application context. – Alex Sep 20 '18 at 05:24
  • treating context as view, breaks somehow that VM shouldn't have ref to view. In cases, when you need to do something with context, imho, it's better to create some context operation wrapper, which can be injected into the VM and called from VM. eg. `class ResController(ctx: Context) { fun getStr(id: Int) = ctx.getString(id) }` - controller can be injected, VM doesn't have ref to view(context in this case) – bovquier Sep 21 '19 at 17:51
21

Finally I got something a simpler explanation, a bit...... ...The AndroidViewModel class is a subclass of ViewModel and similar to them, they are designed to store and manage UI-related data are responsible to prepare & provide data for UI and automatically allow data to survive configuration change.

The only difference with AndroidViewModel is it comes with the application context, which is helpful if you require context to get a system service or have a similar requirement. the bold text makes it clearer to sense it.

Abhishek Gurjar
  • 7,426
  • 10
  • 37
  • 45
user9830926
  • 325
  • 3
  • 3
20

AndroidViewModel is subclass of ViewModel. The Difference between them is we can pass Application Context which can be used whenever Application Context is required for example to instantiate Database in Repository.

AndroidViewModel is a Application context aware ViewModel.

AndroidViewModel:

public class PriceViewModel extends AndroidViewModel {
private PriceRepository priceRepository;

public PriceViewModel(@NonNull Application application) {
    super(application);
    priceRepository= new PriceRepository(application);
    allPrices = priceRepository.getAllPrices();
}

ViewModel:

public class PriceViewModel extends ViewModel {
public PriceViewModel() {
    super();
}

You Should use AndroidViewModel only when you require Application Context.

You should never store a reference of activity or a view that references a activity in the ViewModel.Because ViewModel is designed to outlive a activity and it will cause Memory Leak.

Junaid
  • 1,301
  • 1
  • 15
  • 21
  • 1
    Where is the `Application` value passed from? Is it passed via constructor from another class? – IgorGanapolsky Aug 11 '22 at 14:32
  • 1
    @IgorGanapolsky Yes, it's passed by its Factory class which is abstracted away. Your starting point might be the instantiation of the vm: `by viewmodel`. See `ViewModelProvider.Factory`, [How To](https://medium.com/koderlabs/viewmodel-with-viewmodelprovider-factory-the-creator-of-viewmodel-8fabfec1aa4f). See also its source: [cs.android.com](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelProvider.kt;l=314?q=AndroidViewModelFactory) – FalloutBoy Apr 26 '23 at 17:14
0

Apart from the difference that AndroidViewModel gives you an application context whereas ViewModel does not. The important thing that you must understand is that Google itself recommends using ViewModel and not AndroidViewModel.

So, don't use AndroidViewModel unless it is really necessary.

See this: GOOGLE DOC