First of all, my solution includes FragmentManager.FragmentLifecycleCallbacks, which is a
Callback interface for listening to fragment state changes that happen within a given FragmentManager
and sticks with the separation of concerns, in a way that's shown in the Android Architecture Blueprints, I'd say.
Activity creates Presenter, passing along View/ Fragment, so that
Presenter knows its View and furthermore sets itself its Presenter
In Activity's onCreate I register a FragmentLifecycleCallbacks listener by 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 gets notified after the Fragment has returned from its onActivityCreated to make sure, that only for each new Fragment instance added by the ViewPager a new Presenter will be created. The fragment could get attached/detached, its view could be created/destroyed a couple of times, nothing needed to be done, still got its Presenter.
Because in case of recreation (e.g. by rotation) the Fragments' onCreate is called before the Activitys one (where the FragmentLifecycleCallbacks listener is registered!), the listener couldn't implement onFragmentCreated, it has to be onFragmentActivityCreated.
For the given new Fragment instance we can then determine which Presenter is needed:
private void createPresenter(Fragment fragment) {
if (fragment instanceof WhateverContract.View) {
WhateverContract.Presenter whateverPresenter =
new WhateverPresenter((WhateverContract.View) fragment);
} else if (...){}
}
The Presenter connects with 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 can then be started in the Fragments onResume.
If there's something wrong or to improve, please let me know :)