Ma2340
Ma2340

Reputation: 737

Android navigation component view decision

I am using Android Navigation Component in my project. What I am not satisfied is the fragment making the decision to do fragment transition to next fragment transition i.e

In my LoginFragment I have this -

viewModel.onLoginPressed(email, password)
                    .observe(viewLifecycleOwner, Observer {
                      if (it.userLoggedIn) {
                                activity?.findNavController(R.id.nav_host_fragment)
                                    ?.navigate(R.id.action_loginFragment_to_productsFragment)
                      }
})

According to me, the view must be dummy and must not do any such decisions of what to do on loginSuccess for example. The viewModel must be responsible for this.

How do I use this navigation component inside viewModel?

Upvotes: 1

Views: 551

Answers (1)

Martin Marconcini
Martin Marconcini

Reputation: 27236

The ViewModel doesn't need to know about navigation, but it knows about events and state.

The communication should be more like:

NavHostActivity -> Fragment -> ViewModel

Your Fragment has Views, and click listeners, and state. The user types a user/password and presses a button. This onClick listener will tell the view model -> (pseudo-code) onUserPressedTheLoginButtonWith(username, password)

The ViewModel in turn will receive this, do what it needs (like check if you're already logged or whatever, perhaps the final decision is to navigate to another fragment).

What the ViewModel will do is expose a LiveData like

val navigationEvent = LiveData<...>

So the viewModel will navigationEvent.postValue(...)

The Fragment should observe this viewModel.navigationEvent.observe(...) { }

And in THERE in the fragment it can either navigate directly or -if you have an Interface- use it like:

yourNavigator.navigateTo(...) //either your VM knows the destination or the yourNavitagor has a navigateToLogin() concrete method, this is all "it depends what you like/prefer/etc.".

In summary

  1. Activity Host contains Nav code, irrelevant.
  2. Fragment(s) can communicate to a NavDelegate created by you (and likely injected) or Fragments simply know the details and do it by themselves.
  3. Fragment(s) observe the navigation state/event from the viewModel.
  4. Fragment(s) push events from the UI (clicks, actions, etc.) to this viewModel
  5. The ViewModel decides what to do and updates the "liveData"(s) (there can be more than one type of thing you want to observe, not only navigation).
  6. The Fragment(s) react to this observation and act accordingly, either doing it themselves or delegating (step 2 ^).

That's how I'd do it.

Upvotes: 1

Related Questions