1

我已经迁移到 Mosby 3.0.3,现在正在研究PresenterManager. 对我来说,关于 Activity、Fragment 和 ViewGroup 的演示者的生命周期并不完全清楚。我已经查看了ViewGroupMvpDelegateImplFragmentMvpDelegateImpl并且ActivityMvpDelegateImpl无法 100% 确定演示者何时被终止。

据我了解,默认情况下keepPresenterInstance总是keepPresenterOnBackstack如此,我们有这样的情况:

  1. Fragment 的 Presenter 一直存在,直到它的 Fragment 从 backstack 中移除或整个进程终止。在这种情况下,我依赖以下方法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();
    }
    

但是 childFragmentManagers 中的 Fragments 或 FragmentPagerAdapter 中的 Fragments (也在另一个 Fragment 中)呢?

  1. Activity 和 ViewGroup 的 Presenter 一直存在,直到他们的 Activity 未完成或整个过程终止。在这种情况下,我依赖以下方法ActivityMvpDelegateImpl

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

对于所有 ViewGroup,无论它们位于何处,都是如此吗?

问这个问题的原因是,在我们的应用程序中,我们有活动、片段、片段内的片段、自定义视图组,它们都有演示者。这个想法是在presenter中释放大量资源,detachView(final boolean retainInstance)但在内存中保留一些轻量级的东西——比如inMemory缓存,以便在视图从后台恢复时重用它。

同样,我们使用 Dagger2,了解何时发布适当的子组件很重要。

4

1 回答 1

3
  • 活动:当活动完成(或活动进程死亡)时,演示者被销毁(从演示管理器中删除,因此可以被垃圾收集)。因此,活动在屏幕方向更改期间以及在后台堆栈上(如果后台堆栈上有多个活动)保持演示者。与 Mosby 2.x 中的工作方式完全相同

  • 片段:在 Mosby 2.x 中,Presenter 仅在您设置时才会在屏幕方向更改时保留Fragment.setRetainInstanceState(true). 这在 Mosby 3.x 中不再需要,因为 Mosby 3.x 使用 PresenterManager 来保持演示者的方向变化。此外,如果 Fragment 在后堆栈上,Mosby 3.x Presenter 将被保留。这意味着,即使 Fragment 没有 View,因为 Fragment 位于后堆栈上,因此 UI 小部件已被销毁(已调用 Fragment.onDestroyView()),Presenter 实例将被保留,并且如果用户弹出 Fragment 后堆栈以便你回来演示者被重用。然而,当 Fragment 在后台堆栈上时,View 与 Presenter 分离(将调用 presenter.detachView(true))并在 Fragment 位于 Fragment 后台堆栈顶部之后重新连接。这是默认行为,适用于任何类型的 Fragment,包括。ViewPager 和嵌套 ChildFragments 在(子)后堆栈上。FragmentMvpDelegateImpl(keepPresenterInstance, keepPresenterOnBackstack) 在屏幕方向更改期间根本不保留演示者,或者在后堆栈上的片段时不保留演示者。

  • ViewGroups:在 mosby 2.x 中,它们根本无法承受屏幕方向的变化。在 Mosby 3.x 中他们这样做了,因为他们使用 PresenterManager。但是,您必须给每个 ViewGroup 一个 id ( @id/something) 否则 Android 框架不知道如何映射视图(纵向视图到横向视图)。正如您已经正确观察到的那样,ViewGroups 一直保留到“主机活动”消失或 ViewGroup 以编程方式从父 ViewGroup 中删除,例如parentViewGroup.removeChild(indexOfViewGroup). 不管它住在哪里。请注意,如果您将 ViewGroup 放在 Fragment 中,它可能会或可能不会很好地工作。我还没有想过/测试过那个边缘案例。仍然会考虑“主机活动”(而不是将 Fragment 作为父级),但是,如果将 Fragment 放入后堆栈(并推送新的 Fragment),Fragment 的视图可能会出现这种情况包含您的 ViewGroup 将被删除,这类似于以编程方式调用 parentViewGroup.removeChild(indexOfViewGroup)(可能 FragmentManager 在内部调用它)以便您的 ViewGroup 的演示者将被销毁,但它可能不应该被销毁(因为 Fragment 用户可以弹出回栈以便该片段)。在这种情况下,ViewGroup 很可能会创建一个新的 Presenter 实例。如前所述,我还没有测试或考虑过这种边缘情况,但是(据我所知)没有办法获得对“托管片段”的引用,因为 ViewGroup 不知道片段。我建议在 Fragment 中使用 Mosby Fragments 或 Mosby ViewGroups,但不要使用 Mosby ViewGroup(如果确实需要,最好使用子 Fragment)。

您可以通过在相应的 Delegate 构造函数中设置布尔标志来配置所有这些行为。

检测是否按预期工作的最简单方法是将日志添加到 createPresenter() 方法和 persenter.detachView() 方法。Mosby 还提供了一些用于调试的日志记录。您可以在每个委托中启用它,即 FragmentMvpDelegateImpl.DEBUG = true(例如在 Application.onCreate() 中调用它)。请注意,您必须为每个委托(Activity、Fragment、ViewGroup 以及每个变体 Mvp、Mvp+ViewState、Mvi)执行此操作。如果需要,您也可以以相同的方式为 PresenterManager 启用日志记录。

于 2017-05-11T23:52:34.307 回答