9
votes

I've been looking at the Google Android Architecture examples for MVP with Dagger 2:

https://github.com/googlesamples/android-architecture/blob/todo-mvp-dagger/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksActivity.java

But, the example is rather trivial - each Activity has only one Fragment, and the Dagger Component is built in the Activity, and used to inject the Activity with the Presenter for the Fragment.

I've tried building on that example, to add multiple fragments to an Activity and navigate between them. Since each fragment has its own presenter, I've moved the dagger component building into the Fragment. So now I have:

  • FragmentCallback (an interface providing methods to load fragment1 and fragment2)
  • Activity (implements FragmentCallback)
  • Fragment1 (implements the view interface)
  • Fragment1Contract (defines view and presenter interfaces)
  • Fragment1Presenter (implements the presenter interface)
  • Fragment1Component (injects Fragment1)
  • Fragment1Module (provides the view and presenter)
  • Fragment2
  • Fragment2Contract (defines view and presenter interfaces)
  • Fragment2Presenter (implements the presenter interface)
  • Fragment2Component (injects Fragment2)
  • Fragment2Module (provides the view and presenter)

The activity does very little, it just loads the first fragment and implements FragmentCallback which the view can use to switch to another fragment.

The first fragment has a button which loads the second fragment using the FragmentCallback - which the fragments get by casting the Activity via

public void onAttach(Context context) {
    super.onAttach(context);
    callback = (FragmentCallback) context;
}

Am I on a sensible track here? While the code looks clean with MVP am I missing something w.r.t the dagger components and modules?

Thanks.

Update

I've improved my situation a bit by creating one Component and Module for the Activity. Each Fragment still builds the Dagger context, but I'm no longer injecting the view (fragment) in the presenter constructor - when the fragment builds the context, injects itself (so it has the presenter) it then calls presenter.init(this) so that the presenter now has the view.

This nicely reduces the number of classes, and the next step would be to try only building the component in the activity, and having the fragment use this to inject itself (without having to build a new component).

1
Yes you are almost on right track.Javed Salat
Almost? Care to elaborate?prule
@prule Am I on a sensible track here? do you have any problems so far? If no - you're on the right track. It's hard to give not opinionated answer to such question.Dmitry Zaytsev
@DmitryZaitsev I haven't hit any problems with this simple setup, but it seems excessive creating modules and components for every fragment... was wondering if it's possible to create one component for the Activity (covering multiple fragments) or even one for the whole app.prule
Hey @prule, Were you able to solve the problem? I got the same situationMohamed ALOUANE

1 Answers

0
votes

You're definitely on the right track.

I would suggest that you don't use a single component in Activity, but instantiate a separate component per Fragment (even if the components are the same). There are two benefits to this approach:

  • Fragments are not coupled to Activity and to other Fragments by the component itself (and the objects the component could cache if you use scopes)
  • Allows more fine grained employment of scopes (if you ever need to)

Offtopic:

I wrote a blog post about why activities in Android are not UI elements. Have a look, and if you feel like it makes sense, then there is a link to alternative implementation of MVP :)