Android MVP - 屏幕方向 - 保留演示者状态

Android MVP - screen orientation - retain presenters state

我对 Android 中的 MVP 模式有疑问。我想编写我自己的 "application core",它将为演示者、视图等提供基础 类。它必须简单、干净且 "stable"。我的想法与 Mosby 提供的非常相似,我正在努力实现这样的目标:

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

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

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

除了最后一期 - "restart background tasks that has been canceled",我几乎完成了所有事情。用一个例子来讨论它会更容易。假设我在演示者中有两种方法(Retrofit 2 调用):

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

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

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

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

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

从我的角度来看,MVP 只在视图中显示一个模型(而不是您的方案中的两个模型)始终是一个好主意。通常,如果您必须在同一个视图中处理两个模型,这表明您可以将此视图和演示者分成两个不同的部分。

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

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

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

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

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

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

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