Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass data between fragment viewmodels

Tags:

Let me just say up front that this is more of a "structural" question, and I'm not asking anybody to write code; I'm just trying to figure out how I should be structuring my application.

I'm using Android's DrawerLayout/NavigationView for my app. This means that MainActivity is the host for all my fragments.

I currently have three fragments (in reality it's many more, but they are more or less exactly like these three fragments, just for different sets of data).

  • ListFragment
  • DetailFragment
  • EditFragment (used for both adding and editing)

On my ListFragment I have (surprise!) a list of items. This is a LiveData collection on SharedViewModel (which is tied to MainActivity's lifecycle). When an item is tapped I pass the event through to MainActivity by means of an interface listener.

MainActivity then loads up the DetailFragment. In the same call, I load an instance of SharedViewModel (again tied to MainActivity). I set SharedViewModel.selectedItem to be the tapped item. Then, in DetailFragment's onCreate function, I get the selected item via ViewModelProviders.of(activity).get(SharedViewModel::class.java).selectedItem.

On the DetailFragment, there's an edit button. This goes through more or less the same routine described above, but loading up the EditFragment instead. When the edited/added item is saved, I add/replace the item in SharedViewModel's collection through MainActivity's interface listener.

Obviously this is not optimal for several reasons. For one, it means that I've got at least five large sets of data hanging around for MainActivity's lifecycle (the entire lifecycle of the app, essentially). Also, MainActivity grows way out of hand as I have to add more and more functions to handle events.

What I want to do is have, for example, my list of items on a ListFragmentViewModel which is tied to ListFragment's lifecycle. My selected item on a DetailFragmentViewModel, my editing item on an EditFragmentViewModel, etc.

My problem is that I'm not sure how to properly pass the data around in this case. For example, let's say I add a new item in EditFragment. How do I get that into ListFragmentViewModel's collection of items? ListFragment is in the back-stack, so its viewmodel hangs around and doesn't reload the data when it's navigated back to, since it still has the collection from before. This makes sense and is probably how it should be (after all, who wants to wait for all the data to load when they go to DetailFragment and back to ListFragment?), but it means that I don't get my new item in the collection.

That's just one example, but I'm running into quite a few issues like it (e.g. passing the selected item to DetailFragmentViewModel.)

I'm not quite sure what direction I should even be going here. Can someone more experienced help me out?

like image 733
RareNCool Avatar asked Jan 24 '18 14:01

RareNCool


1 Answers

let's say I add a new item in EditFragment. How do I get that into ListFragmentViewModel's collection of items?

EditFragment tells your item repository, "yo! here's a new item!". The item repository arranges to update your backing store, plus emits an event to interested parties notifying about the data change (e.g., emits an event on an RxJava PublishSubject). The ListFragmentViewModel listens for those events and reacts accordingly.

ListFragment is in the back-stack, so its viewmodel hangs around and doesn't reload the data when it's navigated back to, since it still has the collection from before

It should be finding out about the data change from your item repository, and doing whatever makes sense to reflect that data change. That could be simply taking data from the data-change event and updating its in-memory content. That could be re-requesting information from the backing store. In principle, it could be something else.

like image 196
CommonsWare Avatar answered Sep 21 '22 10:09

CommonsWare