I am building an Android App using MVVM and DataBinding. And I have a function inside my ViewModel that starts an Activity. Is it okay to have an onClick call inside a ViewModel?
Like this.
public class MyViewModel {
public void onClick(View view, long productId) {
Context context = view.getContext();
Intent intent = new Intent(context, ProductDetailActivity.class);
intent.putExtra("productId", productId);
context.startActivity(intent);
}
}
And in my XML:
...
android:onClick="@{(v) -> viewModel.onClick(v, viewModel.product.id)}">
Or would it be a best practice to move it to the View and call it from EventBus or Rx and have only POJO in my ViewModel?
The answer to your question is what is your goal?
If you want to use MVVM for separation of concerns so that you can unit test your
Viewmodel
then you should try to keep everything that requires aContext
separate from yourViewmodel
. TheViewmodel
contains the core business logic of your app and should have no external dependencies.However I like where you are going :) If the decision which Activity is opened lies in the View, then it is very very hard to write a JUnit test for it. However you can pass an object into the
Viewmodel
which performs thestartActivity()
call. Now in your Unit test you can simply mock this object and verify that the correctActivity
is openedThat's absolutely perfect to put it inside
ViewModel
, however you need to set yourViewModel
fromActivity
/Fragment
.Here are some links you can follow to learn MVVM architecture.
Approaching Android with MVVM
Android MVVM
https://github.com/ivacf/archi
People-MVVM
MVVM on Android: What You Need to Know
As the principle of MVVM points out that only View (activity/fragment) holds reference to the ViewModel and the ViewModel shouldn't hold reference to any View.
In your case, to start an activity, I will do like this:
MyViewModel.class
And in your MainActivity.class
finally, in your activity_main.xml
The way I do it is, in your ViewModel:
This allows you to check the class of Activity started, and the data passed in the Bundle. Then, in your Activity, you can add this code: