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 :)