简体   繁体   English

主持人在Mosby 3中的一生-MVP

[英]Lifetime of presenter in Mosby 3 - MVP

I've migrated to Mosby 3.0.3 and now investigating abilities of PresenterManager . 我已经迁移到Mosby 3.0.3,现在正在研究PresenterManager For me is not completely clear the lifetime of presenter regarding to Activity, Fragment and ViewGroup. 对我来说,关于Activity,Fragment和ViewGroup的演示者的生命周期还不是很清楚。 I've looked through ViewGroupMvpDelegateImpl , FragmentMvpDelegateImpl and ActivityMvpDelegateImpl and couldn't 100% be sure when presenter is terminated. 我已经查看了ViewGroupMvpDelegateImplFragmentMvpDelegateImplActivityMvpDelegateImpl ,不能100%确定演示者何时终止。

As far as I understand by default keepPresenterInstance and keepPresenterOnBackstack are always true and we have such situation: 据我了解,默认情况下keepPresenterInstancekeepPresenterOnBackstack始终为true,我们有以下情况:

  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 : 在这种情况下,我依赖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)? 但是childFragmentManagers中的片段或FragmentPagerAdapter中的片段(也位于另一个片段中)呢?

  1. Activity's and ViewGroup's presenters exist until theirs's activity isn't finished or the whole process is terminated. 活动和ViewGroup的演示者一直存在,直到他们的活动没有完成或整个过程终止为止。 In this case I rely on method from ActivityMvpDelegateImpl : 在这种情况下,我依靠ActivityMvpDelegateImpl方法:

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

Is this true for all ViewGroups, wherever they are resided? 对于所有ViewGroup,无论它们位于何处,这都是真的吗?

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. 这个想法是在detachView(final boolean retainInstance) Presenter中释放大量资源,但在内存中保留一些轻量级的东西(例如inMemory缓存),以便在从后堆栈恢复视图时重用它。

Likewise we use Dagger2 and it's important to understand when to release appropriate subcomponent. 同样,我们使用Dagger2,了解何时发布适当的子组件很重要。

  • Activity: Presenter gets destroyed (removed from Presentation Manager and therefore can be garbage collected) when Activity gets finished (or on Activity Process death). 活动:活动结束时(或在“活动流程”死亡时),演示者被销毁(从Presentation Manager中删除,因此可以被垃圾回收)。 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 与Mosby 2.x中的工作原理几乎相同

  • Fragments: In Mosby 2.x Presenter were only kept across screen orientation changes if you set Fragment.setRetainInstanceState(true) . 片段:如果您设置Fragment.setRetainInstanceState(true)则在Mosby 2.x Presenter中仅在屏幕方向变化之间保持一致。 This is not required anymore in Mosby 3.x because Mosby 3.x uses PresenterManager to keep presenter across orientation changes. 在Mosby 3.x中,这不再是必需的,因为Mosby 3.x使用PresenterManager来保持演示者跨方向更改。 Also, since Mosby 3.x Presenter will be kept if fragment is on the back stack. 另外,由于Mosby 3.x Presenter如果片段位于后堆栈上,将被保留。 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. 这意味着,即使Fragment没有视图,因为Fragment在后台堆栈上,因此UI部件已被破坏(Fragment.onDestroyView()已被调用),Presenter实例也将保留,并且如果用户将Fragment往后弹出,则您回来时,演示者已被重用。 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. 但是,当Fragment在后台堆栈上时,View从Presenter分离(将调用presenter.detachView(true)),并在Fragment是片段后台堆栈顶部的Fragment之后重新连接。 This is the default behavior and works for any kind of Fragment incl. 这是默认行为,适用于任何种类的Fragment incl。 ViewPager and Nested ChildFragments on (child)back stack. ViewPager和(child)back堆栈上的嵌套ChildFragments。 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. 您可以将其配置为FragmentMvpDelegateImpl(keepPresenterInstance, keepPresenterOnBackstack)构造函数参数,以在屏幕方向更改期间完全不保留演示者,或者在后向堆栈中的片段时不保留演示者。

  • ViewGroups : In mosby 2.x they didn't survive screen orientation changes at all. ViewGroups :在mosby 2.x中,它们根本无法幸免于屏幕方向更改。 In Mosby 3.x they do, because they use PresenterManager. 在Mosby 3.x中,它们可以这样做,因为它们使用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). 但是,您必须给每个ViewGroup一个id( @id/something ),否则Android Framework不会知道如何映射视图(从人像视图到横向视图)。 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) . 正如您已经正确观察到的那样,ViewGroups会保留到“主机活动”消失或以编程方式像parentViewGroup.removeChild(indexOfViewGroup)一样从父ViewGroup中删除ViewGroup 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. 请注意,如果将ViewGroup放在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). 仍然会考虑“主机活动”(而不是将片段作为父级活动),但是,如果将片段放回堆栈(并推入新的片段),则可能是这种情况包含您的ViewGroup的对象将被删除,这类似于以编程方式调用parentViewGroup.removeChild(indexOfViewGroup) (也许FragmentManager在内部调用此方法),因此您的ViewGroup的演示者将被销毁,但可能不会被删除(因为Fragment用户可以弹出堆栈,以便分段)。 In that case it is likely that ViewGroup creates a new Presenter instance. 在这种情况下,ViewGroup可能会创建一个新的Presenter实例。 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. 如前所述,我还没有测试也没有考虑过这种极端情况,但是(据我所知)由于ViewGroup不了解Fragment,因此没有办法(据我所知)获得对“宿主Fragment”的引用。 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). 我建议在片段中使用Mosby片段或Mosby ViewGroup,但不要使用Mosby ViewGroup(如果确实需要,最好使用子片段)。

You can configure all that behavior by setting boolean flag in corresponding Delegate constructor. 您可以通过在相应的Delegate构造函数中设置布尔标志来配置所有这些行为。

The easiest way to detect if that works as expected is to add logs to createPresenter() methods and persenter.detachView() method. 检测日志是否按预期工作的最简单方法是将日志添加到createPresenter()方法和persenter.detachView()方法。 Also Mosby provides some logging for debugging. Mosby还提供了一些日志记录以进行调试。 You can enable that in each delegate ie FragmentMvpDelegateImpl.DEBUG = true (for example call this in Application.onCreate()). 您可以在每个委托中启用它,即FragmentMvpDelegateImpl.DEBUG = true(例如,在Application.onCreate()中调用它)。 Please note you have to do that for each delegate (Activity, Fragment, ViewGroup and also for each variant Mvp, Mvp+ViewState, Mvi). 请注意,您必须为每个委托(Activity,Fragment,ViewGroup以及每个变体Mvp,Mvp + ViewState,Mvi)执行此操作。 You can also enable logging for PresenterManager in the same way if you want to. 如果需要,您也可以以相同的方式启用PresenterManager的日志记录。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM