12

Using the new Navigation Architecture Component, I've got a single activity as a navhost with multiple fragments for my screens. Right now I have an EditProfileFragment where the user can click a button and another fragment opens, with a list of countries to choose from. Let's say I want to share the result of that country selection back to the EditProfileFragment. The general idea is that I'll have a single EditProfileViewModel for all "edit profile" actions.

  1. How do I share the selected country between those fragments? I'm thinking using a shared viewmodel, but I'm hesitant scoping it to the activity because I don't want it to persist when the user completes the "edit profile" flow.

  2. Are there any other clean/recommended approaches I should consider? Maybe a singleton that temporarily holds that value?

papageorgiouk
  • 216
  • 5
  • 14
  • could you just clear it out once it's completed? or pass a flag when creating a new fragment to start fresh and ignore any stale/transient data? – Mateo Nov 20 '18 at 01:59
  • @Mateo Yes I could. I was just wondering if there was a cleaner solution – papageorgiouk Nov 20 '18 at 18:05
  • @papageorgiouk Did you find a nice solution for this problem? I'm facing the exact same situation, with a country selector fragment :) – datiKaa Dec 11 '18 at 09:46
  • @DaTi I went with the repository pattern and having an object for temporarily holding shared state. There should be a 1-to-1 relationship between ViewModel and View(controller), so I think this is the best approach. – papageorgiouk Dec 12 '18 at 08:06

2 Answers2

2

It's easier with a shared view model indeed, but as you said, it comes with other concerns like scoping the view model to a higher context for simple information exchange.

IMHO shared view model is not a bad approach in certain scenarios. I was working on an app which has 5 tabs, first tab was like a summary of 2nd and 3rd ones. It was a good choice to use shared view model, since I was just reusing the data, just changing the number of items adapter shows in corresponding views, logic was being reused.

It sounds like you have common logic / items in your profile & profile edit page. I don't know how many, but if you feel like it's not enough to share a view model between these two, remember just because you are using view models doesn't mean you have to use them to share / store / pass around some data. For example :

  • Navigate to previous fragment with acquired data.
  • You can save "profile" to persistence and change what's stored. When your view model for profile is (re)created, it gets the latest value from persistence.
  • You can update your profile in server directly, and fetch it again on profile.
  • You can mix these two above.
Mel
  • 1,730
  • 17
  • 33
  • Persistence isn't an option, unfortunately. – papageorgiouk Nov 27 '18 at 17:32
  • Do you have any kind of DI ? You can scope profile model to activity so fragments will get same instance. – Mel Nov 28 '18 at 10:42
  • Scoping to activity isn't a problem. But my app is Single-Activity (with the new navigation component), so I'd rather not scope it to that activity (which essentially means it will be app-scoped) – papageorgiouk Nov 29 '18 at 07:59
  • Sorry, I think "model" is a bit confusing in this context, I meant profile entity, not view model. – Mel Nov 29 '18 at 09:18
-1

Answering my own question on how I resolved this for future reference:

Because I wanted to keep the 1-to-1 relationship between ViewModel-View(controller)/Fragment, I went with a UserRepository that holds a "temporary state" object for cases like this.

papageorgiouk
  • 216
  • 5
  • 14
  • 1
    Thanks for sharing this. Can you provide more info about your `UserRepository`? What scope does it have? When do you create it and how do you manage to clear the temporary state? – konata Dec 14 '18 at 16:53
  • @konata App-scoped and letting Dagger initialise it whenever. Temp state is an inner class object implementing the builder pattern, and disposed of manually when we're done with it. – papageorgiouk Dec 18 '18 at 15:34