Firstly, my solution includes the FragmentManager.FragmentLifecycleCallbacks , which is
Callback interface for listening to fragment state changes that occur in the given FragmentManager
and adheres to separation of concerns, as shown in Android Architecture Blueprints , I would say.
Activity creates a Presenter by going through View / Fragment , so thatPresenter knows its View and, in addition, sets its Presenter
In Activity onCreate I register the FragmentLifecycleCallbacks listener, calling this
private void registerFragmentsLifecycleListener() { // All registered callbacks will be automatically unregistered when // this FragmentManager is destroyed. getSupportFragmentManager.registerFragmentLifecycleCallbacks( new FragmentManager.FragmentLifecycleCallbacks() { // Called after the fragment has returned from its onActivityCreated @Override public void onFragmentActivityCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) { createPresenter(f); } }, false); // true to register callback for all child FragmentManagers }
The listener receives a notification after the Fragment returns from its onActivityCreated , to ensure that only for each new Fragment instance added by the ViewPager new Presenter will be created. A fragment can be attached / detached, its view can be created / destroyed a couple of times, nothing had to be done, I still got Presenter .
Because in case of rest (for example, by rotation) Fragment s' onCreate is called before Activity one (where the FragmentLifecycleCallbacks listener is registered!), The listener could not implement onFragmentCreated , it must be onFragmentActivityCreated .
For this new Fragment instance, we can determine which Presenter needed:
private void createPresenter(Fragment fragment) { if (fragment instanceof WhateverContract.View) { WhateverContract.Presenter whateverPresenter = new WhateverPresenter((WhateverContract.View) fragment); } else if (...){} }
Presenter connects to its View / Fragment in the constructor
private final WhateverContract.View mView; public WhateverPresenter(@NonNull WhateverContract.View view) { mView = checkNotNull(view, "view cannot be null!"); mView.setPresenter(this); }
and then can be run in Fragment onResume .
If something is wrong or improve, let me know :)