BAZTED
BAZTED

Reputation: 546

Dagger 2 Scope for Fragments communication

I have existing Single Activity Application. I am trying to make it a little bit better as there is case which makes me sick the most. Lets imagine flow how application currently works on example, just for better picture:

F1 shows us list of contacts

F2 shows us contact details(pressing edit btn)

F3 shows edit form for contact(selecting change country)

F4 shows us list of countries to select(picker)

All of them are just replaced and added to backstack. So issue in this flow is that, there is no clean possibility to pass result from F4 to F3. Or maybe there is but I do not see it. Previous developer decided to allow each fragment to update db model on each of screen. Means that when you pick country F4 updates contact model created just for edition in F3, which is duplication of original model visible on F2

I would strongly like to change because it irritates me the most. Thankfully I have Dagger 2, with more or less structure as on sketch. enter image description here

@PickerScope is something I am trying to add for solution of my problem. Maybe the naming is not clear enough, as it will work for fragment communication, naming is always an issue :) I would like to create XPickerSubComponent is component that will be created for each communication. And module in it will just allow me to keep data that should be used for communication. What do you think about such approach are there any better ideas? And the most crucial for me, how should I manage @PickerScope lifecycle and where? Activity as for me is single place to make it. Creation will be called on entering F3 and destroy on Saving/Canceling in F3. I understand that question is pure and I am asking for creative solutions. But I just need to know if light side is strong enough and can find better way to do it.

Upvotes: 1

Views: 830

Answers (2)

David Rawson
David Rawson

Reputation: 21417

Dagger 2 works well if you follow existing Android design patterns.

Bearing that in mind, are you sure you want to enter a world of pain to have your Fragments communicating results to each other? The developers' guide says:

All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.

You seem to be advocating some kind of shared object for communication between Fragments. This would probably go against the guidelines from the developers' guide:

In order to reuse the Fragment UI components, you should build each as a completely self-contained, modular component that defines its own layout and behavior.

It's easier to let the hate flow through you hate another dev's code rather than try to understand it. Have another look - it might not be that bad. I am not sure what you mean by "model" in your question but if all the Fragments have their own unique view-model that is instantiated from a db query in onActivityCreated() (using, for instance, a Loader) or from data passed in from the Activity in setArguments(Bundle bundle) then perhaps that is not so bad. In this case, adding/replacing ensures that that onActivityCreated() is called every time the Fragments become visible and the Fragments will remain autonomous in accordance with the developers' guide recommendation. You can always use Dagger 2 to clean up the code by injecting dependencies that are shared between your Fragments and/or Activity.

However, I suspect your current setup not a very good use case for Fragments altogether. For the very least, your "contact list" should probably be in a separate Activity from "edit contacts". Then you could use onActivityResult() to communicate the result from an EditContactActivity to a ContactListActivity if this is even necessary.

Upvotes: 2

Peddro
Peddro

Reputation: 1145

Other option is to use dagger to provide an object for you. Lets say you have an object FormData. You can initialize it in your appmodule.

@provides @Singleton FormData provideFormData { return new FormData() }

@Singleton
Public class FormData {

@Inject public FormData() {}

}

Then, In your fragment just inject formdata.

————————

You can also.create a scope and a component for your forms which contains the fragments F1, F2 etc. With this you will have to create yet another scope for all fragments that are not of FormScope

Upvotes: 1

Related Questions