Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best approach to start an Activity from ViewModel in MVVM Architecture

I am following MMVM architecture in app, Everything was working fine untill I got a crash using following code to start an activity from ViewModel. Method is called from XML using databindings and passing view as parameter and getApplication() is the method from AndroidViewModel class.

getApplication().startActivity(new Intent(view.getContext(), MyActivity.class));

I believe it was because I am not using NEW_TASK flag since I am starting activity outside an Activity class.

Now there are following solutions I could think of but not sure which one is best based on architectural point of view.

1. ViewModel with a method which takes Activity as parameter and call that method from a fragment

public startMyActivity(Activity activity){
   activity.startActivity(new Intent(activity, MyActivity.class));
}

Now add a listner something like this in fragment

mBinding.myButton.setOnClickListener(){
    viewModel.startMyActivity(getActivity());  
}

2. Adding a New Task flag to intent and keep it in ViewModel itself

Intent myIntent = new Intent(view.getContext(), MyActivity.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
getApplication().startActivity(myIntent);

3. Start the Activity from fragment itself

mBinding.myButton.setOnClickListener(){
   activity.startActivity(new Intent(activity, MyActivity.class));
}

I believe all these approaches works fine but a question in mind

Is it ok to have listeners seprately in Fragment insted of using binded ViewModels to call method from view xml ?

I am not sure about the second approach if that will still crash the app in some OS.

Which one is the best approach from architecture point of view and unit test prespective ?

like image 488
Piyush Agarwal Avatar asked Mar 15 '18 05:03

Piyush Agarwal


People also ask

How do I share my ViewModel between activities?

In android, we can use ViewModel to share data between various fragments or activities by sharing the same ViewModel among all the fragments and they can access everything defined in the ViewModel. This is one way to have communication between fragments or activities.

How do I start a ViewModel activity in Kotlin?

You should call startActivity from activity, not from viewmodel. If you want to open it from viewmodel, you need to create livedata in viewmodel with some navigation parameter and observe on livedata inside the activity.

How do you communicate between view and ViewModel?

What is a proper way to communicate between the ViewModel and the View , Google architecture components give use LiveData in which the view subscribes to the changes and update itself accordingly, but this communication not suitable for single events, for example show message, show progress, hide progress etc.


1 Answers

I would go for navigation inside activities/fragments but of course most case you wanna trigger your navigation from view model. So you need to use a command from you view model to notify your view (activity/fragment) to navigate elsewhere. You can do this kind of "command" using LiveData and more specificly SingleLiveEvent.

SingleLiveEvent is like any LiveData but trigger an event only when you explicity set a value to it, for example you won't receive its value when starting observing it from your view (activity/fragment)

like image 189
Samuel Eminet Avatar answered Sep 21 '22 21:09

Samuel Eminet