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 Fragment
s' onCreate
is called before the Activity
s 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 Fragment
s onResume
.
If there's something wrong or to improve, please let me know :)