【问题标题】:Android MVP - screen orientation - retain presenters stateAndroid MVP - 屏幕方向 - 保留演示者状态
【发布时间】:2015-11-20 16:45:28
【问题描述】:

我对 Android 中的 MVP 模式有疑问。我想编写自己的“应用程序核心”,它将为演示者、视图等提供基类。它必须简单、干净且“稳定”。我的想法与 Mosby 所提供的非常相似,我正在努力实现这样的目标:

  1. 每个Activity都有自己的PresenterView(界面 与 Activity 通信),ViewState(可包裹的对象 保存持久数据)。
  2. Activity销毁时:

    • 分离视图
    • 将 ViewState 保存在包中
    • 取消 Presenter 中的所有后台任务(完成后更新视图的任务)
    • 销毁 Presenter
  3. Activity重新创建时:

    • 附加视图
    • 恢复 ViewState
    • 创建 Presenter 的新实例
    • 重启已取消的后台任务

除了上一期 - “重新启动已取消的后台任务”,我几乎完成了所有工作。用一个例子来讨论它会更容易。因此,假设我在演示者中有两种方法(Retrofit 2 调用):

  • downloadUsers() - 从网络服务器和 onSuccess 更新视图中获取用户数据
  • downloadProject() - 从 Web 服务器和 onSuccess 更新视图中获取项目信息

现在,当其中一个调用已启动但尚未完成时,用户正在更改配置。 在重新创建 Presenter 时,我如何知道应该重新启动其中的哪一个?

我想到的唯一想法是为每个任务创建一个持久的布尔标志,在任务开始时将其设置为 true,在任务完成时设置为 false。创建 Presenter 时,我将检查每个标志并重新启动相应的调用。

你怎么看?如何改进?还有其他想法吗?

【问题讨论】:

    标签: android retrofit mvp mosby


    【解决方案1】:

    我不知道您的 UI 是什么样子,但对我来说,您应该将一个大视图拆分为两个子视图:

    • DownloadUsersView + ViewState 由 DownloadUsersPresenter 管理
    • DownloadProjectsView + ViewState 由 DownloadProjectsPresenter 管理

    从我的角度来看,MVP 有一个在视图中显示的模型总是一个好主意(而不是像您的场景中那样两个)。通常,如果您必须在同一个视图中处理两个模型,则表明您可以将此视图和演示者拆分为两个不同的。

    或者,您可以将两个模型合并为一个模型,例如

    class DownloadModel {
      List<User> users;
      List<Project> projects;
    }
    

    然后你结合你的两个改造调用来创建一个DownloadModel,当两个调用都完成后你可以在你的视图中显示DownloadModel。使用改造和 rxjava,这非常简单(参见 combineLatest() 运算符)。在这种情况下,您就没有这个问题,因为您的 Presenter 只有一个 download() 方法可以同时下载两者。如果一个明显快于另一个,那么很可能在方向更改和演示者重新创建之后,更快的一个来自改造缓存,所以这应该不会打扰你。

    正如您已经说过的,您还可以开始在演示者中跟踪之前执行的 http 调用,并在演示者重新实例化后重新调用它们,但这意味着演示者必须将其内部状态也保存到捆。 Mosby 没有对此做出任何说明,并假设一般情况下没有这种需要。因此 Mosby 的默认 Presenter 实现不提供 presenter.saveInstanceState(Bundle)presenter.restoreInstanceState(Bundle)。但这并不意味着您不能/不应该这样做。你可以在 Mosby 和你的实现中做到这一点。但是,如果您开始这样做,那么您只需将之前位于 Activity 类中的意大利面条代码(没有 mvp)移动到演示者中。

    因此,我再次强烈建议在 MVP 中为每个视图使用一个模型。

    顺便说一句。为什么要重新发明轮子?听起来 Mosby 已经提供了您正在寻找的东西。 Mosby 还支持在屏幕方向更改后保留演示者。

    【讨论】:

    • 感谢您的全面回答。我这样做主要是出于教育目的 - 我想玩弄泛型,了解 android 生命周期并学习如何不造成内存泄漏:) 我想将演示者的状态包含到 VIewState 中,并将所有内容保存并恢复到一个包中。但现在我发现这是个坏主意。意大利面的好点。我同意 Presenter 应该只处理一个模型。我在上面的例子中挑选了不幸的名字。让我们将其更改为: downloadUsers() - 改造调用; storeUsers() - 将下载的数据保存在数据库中。我是否也应该使用 Rx 找到解决方案?
    • @rafakob 您的问题是您将 MVP 视为有关异步后台任务调度的所有问题的解决方案。 MVP 的主要目的是将 View 与 Model 分离,并让一个 Presenter 作为“协调者”坐在两者之间。在您的示例中:storeUsers() 在它自己的 android 服务中执行可能是个好主意,因为您不想在屏幕方向更改时重新执行 storeUser(),对吧?所以在服务中执行storeUser(),让演示者观察服务(eventbus、rxjava 或任何你喜欢的东西)。
    【解决方案2】:

    有很多方法和解决方案。我喜欢的一个是使用 Loaders api。这是一个简单的库,您可以使用它来在方向更改https://github.com/samiuelson/Preservely 中持久化演示者实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-27
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多