Mosby 3 中主持人的一生 - MVP
Lifetime of presenter in Mosby 3 - MVP
我已经迁移到 Mosby 3.0.3,现在正在研究 PresenterManager
的能力。
对我而言,关于 Activity、Fragment 和 ViewGroup 的 Presenter 生命周期并不完全清楚。
我查看了 ViewGroupMvpDelegateImpl
、FragmentMvpDelegateImpl
和 ActivityMvpDelegateImpl
,但无法 100% 确定演示者何时终止。
据我了解,默认情况下 keepPresenterInstance
和 keepPresenterOnBackstack
总是正确的,我们有这样的情况:
片段的呈现器一直存在,直到它的片段从后台堆栈中删除或整个过程终止。在这种情况下,我依赖 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 中的片段或 FragmentPagerAdapter 中的片段(也在另一个片段中)呢?
Activity 和 ViewGroup 的演示者存在,直到他们的 activity 未完成或整个过程终止。在这种情况下,我依赖 ActivityMvpDelegateImpl
:
中的方法
static boolean retainPresenterInstance(boolean keepPresenterInstance, Activity activity)
{
return keepPresenterInstance && (activity.isChangingConfigurations()
|| !activity.isFinishing());
}
是否所有 ViewGroup 都如此,无论它们位于何处?
之所以问这样的问题是因为在我们的应用程序中,我们有活动、片段、片段中的片段、自定义视图组,并且所有这些都有演示者。
这个想法是在detachView(final boolean retainInstance)
中释放presenter中的大量资源,但在内存中保留一些轻量级的东西——比如inMemory缓存,以便在视图从backstack恢复时重用它。
同样,我们使用 Dagger2,了解何时发布适当的子组件很重要。
Activity: 当 Activity 完成(或 Activity 进程死亡)。因此 activity 在屏幕方向更改期间以及在返回堆栈中保留演示者(如果返回堆栈上有多个活动)。与 Mosby 2.x
中的工作方式完全相同
片段: 在 Mosby 中 2.x 如果您设置 Fragment.setRetainInstanceState(true)
,Presenter 仅在屏幕方向更改时保持不变。这在 Mosby 3.x 中不再需要,因为 Mosby 3.x 使用 PresenterManager 来保持演示者跨越方向变化。此外,由于 Mosby 3.x 如果片段在返回堆栈中,Presenter 将被保留。这意味着,即使 Fragment 没有视图,因为 Fragment 在后台堆栈上,所以 UI 小部件已被销毁(Fragment.onDestroyView() 已被调用),Presenter 实例将被保留,如果用户弹出片段返回堆栈,以便您返回演示者被重用。但是,当 Fragment 在返回堆栈上时,View 与 Presenter 分离(presenter.detachView(true) 将被调用)并在 Fragment 位于片段返回堆栈顶部之后重新附加。这是默认行为,适用于任何类型的片段,包括。 ViewPager 和 Nested ChildFragments on (child)back stack。您可以将其配置为 FragmentMvpDelegateImpl(keepPresenterInstance, keepPresenterOnBackstack)
的构造函数参数,以在屏幕方向更改期间完全不保留演示者,或者在返回堆栈上的片段时不保留演示者。
ViewGroups:在 mosby 2.x 中,它们根本无法承受屏幕方向的变化。在 Mosby 3.x 他们这样做,因为他们使用 PresenterManager。但是,您必须为每个 ViewGroup 提供一个 ID (@id/something
),否则 Android 框架不知道如何映射视图(纵向视图到横向视图)。正如您已经正确观察到的那样,ViewGroup 一直保留到 "host activity" 终止或 ViewGroup 像 parentViewGroup.removeChild(indexOfViewGroup)
一样以编程方式从父 ViewGroup 中删除。它位于何处无关紧要。请注意,如果将 ViewGroup 放入片段中,它可能会或可能不会正常工作。我还没有想过/测试过那个边缘案例。它仍然会考虑 "host activity"(而不是 Fragment 作为父级),但是,如果 Fragment 将被放入返回堆栈(并推送一个新的 Fragment),则可能会出现这种情况包含您的 ViewGroup 的片段将被删除,这类似于以编程方式调用 parentViewGroup.removeChild(indexOfViewGroup)
(也许 FragmentManager 在内部调用它),以便您的 ViewGroup 的演示者将被销毁,但它可能不应该(因为 Fragment 用户可以 pop backstack 以便分段)。在这种情况下,ViewGroup 很可能会创建一个新的 Presenter 实例。正如已经说过的,我还没有测试也没有考虑过这种边缘情况,但是没有办法(据我所知)获得对 "hosting Fragment" 的引用,因为 ViewGroup 不知道片段。我建议在 Fragment 中使用 Mosby Fragments 或 Mosby ViewGroups 但不要使用 Mosby ViewGroup(如果确实有必要,最好使用子片段)。
您可以通过在相应的委托构造函数中设置布尔标志来配置所有这些行为。
检测是否按预期工作的最简单方法是将日志添加到 createPresenter() 方法和 persenter.detachView() 方法。 Mosby 还提供了一些用于调试的日志记录。您可以在每个委托中启用它,即 FragmentMvpDelegateImpl.DEBUG = true(例如在 Application.onCreate() 中调用它)。请注意,您必须为每个委托(Activity、Fragment、ViewGroup 以及每个变体 Mvp、Mvp+ViewState、Mvi)执行此操作。如果需要,您也可以以相同的方式为 PresenterManager 启用日志记录。
我已经迁移到 Mosby 3.0.3,现在正在研究 PresenterManager
的能力。
对我而言,关于 Activity、Fragment 和 ViewGroup 的 Presenter 生命周期并不完全清楚。
我查看了 ViewGroupMvpDelegateImpl
、FragmentMvpDelegateImpl
和 ActivityMvpDelegateImpl
,但无法 100% 确定演示者何时终止。
据我了解,默认情况下 keepPresenterInstance
和 keepPresenterOnBackstack
总是正确的,我们有这样的情况:
片段的呈现器一直存在,直到它的片段从后台堆栈中删除或整个过程终止。在这种情况下,我依赖
中的方法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 中的片段或 FragmentPagerAdapter 中的片段(也在另一个片段中)呢?
Activity 和 ViewGroup 的演示者存在,直到他们的 activity 未完成或整个过程终止。在这种情况下,我依赖
中的方法ActivityMvpDelegateImpl
:static boolean retainPresenterInstance(boolean keepPresenterInstance, Activity activity) { return keepPresenterInstance && (activity.isChangingConfigurations() || !activity.isFinishing()); }
是否所有 ViewGroup 都如此,无论它们位于何处?
之所以问这样的问题是因为在我们的应用程序中,我们有活动、片段、片段中的片段、自定义视图组,并且所有这些都有演示者。
这个想法是在detachView(final boolean retainInstance)
中释放presenter中的大量资源,但在内存中保留一些轻量级的东西——比如inMemory缓存,以便在视图从backstack恢复时重用它。
同样,我们使用 Dagger2,了解何时发布适当的子组件很重要。
Activity: 当 Activity 完成(或 Activity 进程死亡)。因此 activity 在屏幕方向更改期间以及在返回堆栈中保留演示者(如果返回堆栈上有多个活动)。与 Mosby 2.x
中的工作方式完全相同
片段: 在 Mosby 中 2.x 如果您设置
Fragment.setRetainInstanceState(true)
,Presenter 仅在屏幕方向更改时保持不变。这在 Mosby 3.x 中不再需要,因为 Mosby 3.x 使用 PresenterManager 来保持演示者跨越方向变化。此外,由于 Mosby 3.x 如果片段在返回堆栈中,Presenter 将被保留。这意味着,即使 Fragment 没有视图,因为 Fragment 在后台堆栈上,所以 UI 小部件已被销毁(Fragment.onDestroyView() 已被调用),Presenter 实例将被保留,如果用户弹出片段返回堆栈,以便您返回演示者被重用。但是,当 Fragment 在返回堆栈上时,View 与 Presenter 分离(presenter.detachView(true) 将被调用)并在 Fragment 位于片段返回堆栈顶部之后重新附加。这是默认行为,适用于任何类型的片段,包括。 ViewPager 和 Nested ChildFragments on (child)back stack。您可以将其配置为FragmentMvpDelegateImpl(keepPresenterInstance, keepPresenterOnBackstack)
的构造函数参数,以在屏幕方向更改期间完全不保留演示者,或者在返回堆栈上的片段时不保留演示者。ViewGroups:在 mosby 2.x 中,它们根本无法承受屏幕方向的变化。在 Mosby 3.x 他们这样做,因为他们使用 PresenterManager。但是,您必须为每个 ViewGroup 提供一个 ID (
@id/something
),否则 Android 框架不知道如何映射视图(纵向视图到横向视图)。正如您已经正确观察到的那样,ViewGroup 一直保留到 "host activity" 终止或 ViewGroup 像parentViewGroup.removeChild(indexOfViewGroup)
一样以编程方式从父 ViewGroup 中删除。它位于何处无关紧要。请注意,如果将 ViewGroup 放入片段中,它可能会或可能不会正常工作。我还没有想过/测试过那个边缘案例。它仍然会考虑 "host activity"(而不是 Fragment 作为父级),但是,如果 Fragment 将被放入返回堆栈(并推送一个新的 Fragment),则可能会出现这种情况包含您的 ViewGroup 的片段将被删除,这类似于以编程方式调用parentViewGroup.removeChild(indexOfViewGroup)
(也许 FragmentManager 在内部调用它),以便您的 ViewGroup 的演示者将被销毁,但它可能不应该(因为 Fragment 用户可以 pop backstack 以便分段)。在这种情况下,ViewGroup 很可能会创建一个新的 Presenter 实例。正如已经说过的,我还没有测试也没有考虑过这种边缘情况,但是没有办法(据我所知)获得对 "hosting Fragment" 的引用,因为 ViewGroup 不知道片段。我建议在 Fragment 中使用 Mosby Fragments 或 Mosby ViewGroups 但不要使用 Mosby ViewGroup(如果确实有必要,最好使用子片段)。
您可以通过在相应的委托构造函数中设置布尔标志来配置所有这些行为。
检测是否按预期工作的最简单方法是将日志添加到 createPresenter() 方法和 persenter.detachView() 方法。 Mosby 还提供了一些用于调试的日志记录。您可以在每个委托中启用它,即 FragmentMvpDelegateImpl.DEBUG = true(例如在 Application.onCreate() 中调用它)。请注意,您必须为每个委托(Activity、Fragment、ViewGroup 以及每个变体 Mvp、Mvp+ViewState、Mvi)执行此操作。如果需要,您也可以以相同的方式为 PresenterManager 启用日志记录。