Alex_297
Alex_297

Reputation: 249

Lifetime of presenter in Mosby 3 - MVP

I've migrated to Mosby 3.0.3 and now investigating abilities of PresenterManager. For me is not completely clear the lifetime of presenter regarding to Activity, Fragment and ViewGroup. I've looked through ViewGroupMvpDelegateImpl, FragmentMvpDelegateImpl and ActivityMvpDelegateImpl and couldn't 100% be sure when presenter is terminated.

As far as I understand by default keepPresenterInstance and keepPresenterOnBackstack are always true and we have such situation:

  1. Fragment's presenter exists until it's fragment is removed from backstack or the whole process is terminated. In this case I rely on method from FragmentMvpDelegateImpl:

    protected boolean retainPresenterInstance() {
    
      Activity activity = getActivity();
      if (activity.isChangingConfigurations()) {
        return keepPresenterInstanceDuringScreenOrientationChanges;
      }
    
      if (activity.isFinishing()) {
        return false;
      }
    
      if (keepPresenterOnBackstack && BackstackAccessor.isFragmentOnBackStack(fragment)) {
        return true;
      }
    
      return !fragment.isRemoving();
    }
    

But what about Fragments in childFragmentManagers or about Fragments from FragmentPagerAdapter (also inside another fragment)?

  1. Activity's and ViewGroup's presenters exist until theirs's activity isn't finished or the whole process is terminated. In this case I rely on method from ActivityMvpDelegateImpl:

    static boolean retainPresenterInstance(boolean keepPresenterInstance, Activity activity) 
    {
        return keepPresenterInstance && (activity.isChangingConfigurations()
            || !activity.isFinishing());
      }
    

Is this true for all ViewGroups, wherever they are resided?

The reason of asking such question is that in our app we have activities, fragments, fragments inside fragments, custom viewgroups and all of them have presenters. The idea is to release huge resources in presenter in detachView(final boolean retainInstance) but keep in memory something lightweight - like inMemory cache, to reuse it when view will be restored from backstack.

Likewise we use Dagger2 and it's important to understand when to release appropriate subcomponent.

Upvotes: 1

Views: 545

Answers (1)

sockeqwe
sockeqwe

Reputation: 15919

  • Activity: Presenter gets destroyed (removed from Presentation Manager and therefore can be garbage collected) when Activity gets finished (or on Activity Process death). So activity keeps presenter during screen orientation changes and also on the back stack (if you have multiple activities on the back stack). Works pretty the same as in Mosby 2.x

  • Fragments: In Mosby 2.x Presenter were only kept across screen orientation changes if you set Fragment.setRetainInstanceState(true). This is not required anymore in Mosby 3.x because Mosby 3.x uses PresenterManager to keep presenter across orientation changes. Also, since Mosby 3.x Presenter will be kept if fragment is on the back stack. That means, even if the Fragment has no View because Fragment is on the back stack so UI widgets has been destroyed (Fragment.onDestroyView() has been called), Presenter instance will be kept and if the user pops the Fragment back stack so that you come back the presenter is reused. However, while Fragment is on the back stack, View is detached from Presenter (presenter.detachView(true) will be called) and gets reattached after Fragment is the one that is on top of fragment back stack. This is the default behavior and works for any kind of Fragment incl. ViewPager and Nested ChildFragments on (child)back stack. You can configure this as constructor parameter of FragmentMvpDelegateImpl(keepPresenterInstance, keepPresenterOnBackstack) to don't keep presenter at all during screen orientation change or to don't keep presenter while fragment on the back stack.

  • ViewGroups: In mosby 2.x they didn't survive screen orientation changes at all. In Mosby 3.x they do, because they use PresenterManager. However, you have to give each ViewGroup a id (@id/something) otherwise Android Framework dont know how to map views (portrait view to landscape view). As you have already observed correctly, ViewGroups are kept until "host activity" dies or ViewGroup gets removed from parent ViewGroup programmatically like parentViewGroup.removeChild(indexOfViewGroup). Doesn't matter where it resides. Please note that it may or may not work well if you put ViewGroup in a Fragment. I haven't thought / tested that edge case yet. Still it will take "host activity" into account (and not the Fragment as parent), however, it might be the case that if a Fragment will be put on the back stack (and push a new Fragment) that the View of the Fragment containing your ViewGroup will be removed which is similar to programmatically calling parentViewGroup.removeChild(indexOfViewGroup) (maybe FragmentManager internally calls this) so that the presenter of your ViewGroup will be destroyed but it might shouldn't (because Fragment user can pop backstack so that fragment). In that case it is likely that ViewGroup creates a new Presenter instance. As already said, I haven't tested nor thought about this edge case yet, but there is no way (as far as I know) to get a reference to the "hosting Fragment" since Fragment is not known to ViewGroup. I recommend to either use Mosby Fragments or Mosby ViewGroups but not Mosby ViewGroup in a Fragment (prefer a child fragment then if really necessary).

You can configure all that behavior by setting boolean flag in corresponding Delegate constructor.

The easiest way to detect if that works as expected is to add logs to createPresenter() methods and persenter.detachView() method. Also Mosby provides some logging for debugging. You can enable that in each delegate i.e. FragmentMvpDelegateImpl.DEBUG = true (for example call this in Application.onCreate()). Please note you have to do that for each delegate (Activity, Fragment, ViewGroup and also for each variant Mvp, Mvp+ViewState, Mvi). You can also enable logging for PresenterManager in the same way if you want to.

Upvotes: 3

Related Questions