Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[todo-mvp-dagger] why presenters are injected into activity and not fragment? #274

Closed
ialmetwally opened this issue Jan 31, 2017 · 5 comments

Comments

@ialmetwally
Copy link

Currently, the approach to inject the presenter for a fragment into the hosting activity only works if the activity hosts a single fragment.

If we have multiple fragments under the same activity, we can't inject all presenters into the activity, because each component will be able to only provide the dependencies for a single presenter (for the very simple case the view).

This also makes things more complicated when the activity is killed but not the fragment, so the presenter must be initialized for each fragment in the back stack when the activity is recreated.

My questions are:

  • What's the idea behind injecting/initializing the presenters in activities and not fragments?
  • In case of Dagger2 how can I inject multiple presenters into the same activity?
@TylerMcCraw
Copy link

TylerMcCraw commented Apr 21, 2017

Hey @ialmetwally,
I agree, it doesn't make sense to have one presenter in an Activity for multiple Fragments, since you're most likely presenting different information for each Fragment.
For this reason I personally feel that it's best to create a presenter for each and every fragment. This is what I am doing for both personal and professional projects.

I know this doesn't answer the question of why they decided to inject the presenter at the Activity level. Maybe they did it simply because they know they were only going to use one Fragment per Activity

@amitav13
Copy link

@TylerMcCraw I've been struggling with this as well. There are still some UI components like the Toolbar that have to be handled by the Activity rather than Fragments. Activities also need to also swap between the fragments displayed. If the Activity has no connection to the Presenter, how do you handle these behaviors? Have any sample app that I could look at? Thanks!

@TylerMcCraw
Copy link

@amitav13
For that scenario, you have a few options.
In general, from an MVP perspective, I treat the Fragment as the View and the Activity as just some auxiliary piece of the view. Presenter shouldn't care/know about what comprises the view.
So, you can solve this by enlisting a listener interface that the Activity implements and whenever your Presenter needs to update the toolbar:
Presenter calls view.updateToolbar() ->
Fragment receives event and forwards event to "ToolbarListener" (which is the Activity) eventListener.updateToolbar() ->
Activity receives the event and updates the Toolbar UI.

You could also solve this via EventBus or some other subscription type design, but if it's a simple event, just stick to a simple interface.

If you need your Activity to notify your presenter, then use your FragmentManager to forward an event towards your Fragment and then have your Fragment call a Presenter method.

Hope this helps :)

@digitalbuddha
Copy link

We have a pr out #356 that will inject Presenters directly into fragments. The general flow: Activity creates a fragment, fragment registers with dagger, dagger injects the presenter directly into the fragment. This should help with use cases such as having a view pager of fragments that each need their own presenter. Thank you for suggestion!

@gastsail
Copy link

gastsail commented Jul 19, 2019

I'm using it the way @TylerMcCraw is pointing out.

For each Fragment inside it hosts activity I inject the presenter, also I'm using Dagger 2 to be cleaner with the injections

Example Fragment

 @Inject
    lateinit var presenter: MapsPresenter


After the Fragment's view is destroyed, I release all the views and jobs (if using coroutines or other service) to be collected by the garbage collector, doing this you can release some memory on a large backstack.

override fun onDestroyView() {
        super.onDestroyView()
        presenter.detachView()
        presenter.detachJob()
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants