【问题标题】:Lifetime of presenter in Mosby 3 - MVPMosby 3 中演示者的生命周期 - MVP
【发布时间】:2017-05-11 17:48:25
【问题描述】:

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

据我了解,默认情况下keepPresenterInstancekeepPresenterOnBackstack 总是正确的,我们有这样的情况:

  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 中的 Fragment 或 FragmentPagerAdapter 中的 Fragment(也在另一个 Fragment 中)呢?

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

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

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

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

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

【问题讨论】:

    标签: android mvp mosby


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

    • 片段:在 Mosby 2.x 中,仅当您设置 Fragment.setRetainInstanceState(true) 时,Presenter 才会在屏幕方向更改时保留。这在 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 框架不知道如何映射视图(纵向视图到横向视图)。正如您已经正确观察到的那样,ViewGroup 会一直保留到“主机活动”终止或 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)。

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

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

    【讨论】:

    • 感谢您如此全面的回答。在 Mosby 文档中查看这些 cmets 会很方便,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    相关资源
    最近更新 更多