Can I register MVP Presenter inside Fragment

If you are using one single Activity to host multiple Fragments and you are also using Dagger 2 to inject the presenter you need you can inject each presenter to each Fragment directly.

My use case story

I'm doing a project with architecture since some months from now since I found out about Android jetpack Navigation Component, I started to migrate all my app views into this pattern.

So, I came across a lot of refactoring doing the process and I was at this situation of don't know what to do with this situation.

Since I used Dagger 2 from the start point to inject my presenters into my Activities, this won't change much doing the same but with Fragments.

I came across the same repository to check how the architecture was supposed to follow with Fragments, which is indeed a good way to do the instantiation of the presenter inside the host Activity if you have only 1 Fragment as a child.

The thing is that if I need to have multiple Fragments inside one host Activity I should make an instance of each presenter and pass it through my FragmentManager inside each Fragment and that I think is not what I was looking at since it adds multiple instantiations of the presenter from the Host Activity.

This leads to one case, having multiple instances inside my host activity for all presenters, and also some interfaces to handle the detaching of the jobs/views if needed.

One simple way to do it with multiple fragments is just not thinking about the host activity and inject the presenters inside each Fragment itself.

Since doing this with Dagger, it makes the injection cleaner.

Take a look at a simple example

class MainMenuActivity : BaseActivity(){

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        inflateMainFragment(savedInstanceState)
    }

      override fun getLayout(): Int {
        return R.layout.activity_main_menu
    }

    fun inflateMainFragment(savedInstanceState: Bundle?){
        if (savedInstanceState == null) {
            val fragment = MainMenuFragment()
            supportFragmentManager
                .beginTransaction()
                .add(R.id.nav_host_fragment, fragment)
                .commit()
        }
    }
}

As you can see , here I dont have any instantiation of any presenters all my navigation should need. Instead, I just inject each presenter I need inside each Fragment

class MapsFragment: BaseMapFragment(), MapContract.MapView {

    private lateinit var mMap: GoogleMap

    @Inject
    lateinit var presenter: MapsPresenter

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_paseo,container,false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        (requireActivity().application as YawpApplication).getAppComponent()?.inject(this)
        presenter.attachView(this)
        setupToolbar()
        setupMap()
    }
}

And making use of the Fragments lifecycle, you can detach all your Fragments views in onDestroyView() method, and also save some memory space when the garbage collector runs.

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

I have found at the official google repo a question that helped me understand it better.

You can check it here


As you can see in Google's samples (https://github.com/googlesamples/android-architecture), Activities create Presenters. Also Views attach to Activity and Presenters get views (Fragments) as parameter.

After Fragment transaction committed or Fragment (view) state restored Presenters get created and take Fragments (views) as parameter than call

view.setPresenter(T presenter); 

methods of views and Presenters get registered to view.

I think creating Presenter in Fragment is not a good practice. First of all they are separate layers. This is illegal for Separation of concerns. And second, if you create presenter in Fragment, you bind your Presenter's life to view's LifeCycle and when Fragment is destroyed and recreated, you create a new presenter but they're different layers.

The model is an interface defining the data to be displayed or otherwise acted upon in the user interface.

The presenter acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.

The view is a passive interface that displays data (the model) and routes user commands (events) to the presenter to act upon that data.

So Activity can act as an overall controller which creates the Presenters and Views and connect them.

enter image description here

If we talk about your question, yes you can register presenter in fragment. But you should avoid creating presenters in fragments which you use as a view.

But there're lot's of different approaches about MVP pattern in Android community like below. https://plus.google.com/communities/114285790907815804707

Why activities are not ui elements? http://www.techyourchance.com/activities-android/