简体   繁体   中英

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?

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM