【问题标题】:Difficulties implementing Model-View-Presenter in Android在 Android 中实现 Model-View-Presenter 的困难
【发布时间】:2014-07-11 12:59:11
【问题描述】:

Model-View-Presenter (MVP) 是一种众所周知的 GUI 应用程序设计模式。对于 Android,在纯 Java 模块中实现业务逻辑有助于测试,而无需 Android 模拟器。

但是,由于对 Android 应用程序的 GUI 有特殊要求,我在 Android 上实现该模式时遇到了困难:

  • 一个 Activity 可能在任何时候被销毁(来电,用户按下主页按钮,......),并且在重新创建时它应该处于与离开时完全相同的状态。这与大多数其他 GUI 应用程序不同。

  • 一个 Activity 可以经历许多生命周期状态。它可能会暂停,在这种情况下不应修改 Activity 的 UI。例如,如果某些数据正在后台加载,如果它处于暂停状态,则无法将其传递到 MVP(Activity)的 View 部分。同样,这是一个不寻常的要求。

我已阅读博客文章 MVP for Android 并查看了 example source code。我试图通过使用 MVP 模式实现的最终目标是能够使用转译器 j2objc 将所有业务逻辑转换为 Objective-C,以便在 iOS 上实现相同的应用程序时可以重用业务逻辑。

有没有人成功地为 Android 实现了 MVP 模式,在这种情况下,我缺少什么?

【问题讨论】:

  • 我想知道的是:如果您的业务逻辑模块是纯 java 而不需要 Context,为什么您的 Activity-lifecycle 很重要?换句话说,为什么这些特殊的 GUI 要求会成为问题?
  • 如果 MVP 的 View 部分在某些点(暂停时)可能不会更新,PresenterModel 应该不知道吗?不应该创建Model 以便以后可以恢复它吗?
  • 有人可能会争辩说,Activity 负责管理生命周期并根据需要设置/暂停/拆除演示者。演示者对您的系统相关 UI 框架的怪癖一点也不明智。

标签: android android-activity mvp j2objc


【解决方案1】:

我建议在不涉及 Activity 的情况下实现 MVP 组件,或许从概念上考虑什么对 Android 和 GWT 都有用。使用带有模拟视图接口的测试驱动开发创建组件,添加测试直到业务逻辑完全实现和验证。 TDD 有助于保持组件的 API 精简(为什么要为不需要的东西编写测试?),这使得组件的移植更容易。

你描述的Activity需求可以概括为平台无关:组件应该是可序列化的(小's',不是专门的Java序列化),并且需要接受生命周期状态事件。这些也可以使用系统功能的模拟进行全面测试。当您完成这一步时,您可能会注意到很少有 Activity 要求是特定于 Android 的,并且可能在其他平台上很有用。避免创建庞大的服务 API;例如,为了支持序列化,所需要的只是存储/加载方法,而不是像Parcel API 这样的东西。我发现在白板上向其他开发人员描述此类服务 API 是一种很好的方式来发现不必要的问题。

接下来,将组件移植到 Android,可能通过创建一个委托给组件并为模拟接口提供 Android 特定实现类的 Activity。第一次应该全部“正常工作”,但实际上可能遗漏了一些要求,因此将它们添加到平台无关部分并重复。

当您准备好移植到 iOS 时,重新实现那些以前模拟的接口。如果这些接口是精简的,那么直接在 Objective-C 中创建它们可能会更容易,导入 j2objc 生成的协议头。例如,j2objc 的NSDictionaryMap 类使用 NSDictionary 实现来实现 java.util.Map——无需编写和翻译 Java 版本,因为它只使用 iOS API。

【讨论】:

  • 您好,感谢您的想法。我不完全确定component 是什么。你是在说主持人吗?在您的帖子中,我觉得您实际上是在描述称为Presenter-First 的实现过程,我在这方面是否正确?视图应该是接口(没有平台细节),这些应该由 Android 上的 Activity 实现。我觉得实现保存/加载过程需要付出相当大的努力,这也是对 Android 重新创建过程的有效重新实现。
  • 我将组合的 MVP“单元”称为组件,有更好的名称吗?所有可用的术语似乎都超载了。您对 Presenter-First 的看法是正确的,感谢您提供的链接,因为我没有阅读那篇论文。应该从特定于平台的归档服务(如 Parcel 或 Java 的序列化)从外部调用保存/加载——所有组件应该处理的是它自己的存储/恢复。通过使其成为一项服务,Android 特定代码将使用与 Android 应用程序通常使用的代码相同的代码。
【解决方案2】:

我发现围绕 Android 构建的 MVP 变体是朝着隔离应用程序中业务逻辑的正确方向迈出的一步。但是,如果您想实现更好的关注点分离,并因此获得更多可重用的域/业务逻辑,我建议使用Presenter First pattern(您在评论中简要提及自己)。除了减少耦合之外,它还非常适合 TDD,并允许您对所有业务逻辑进行单元测试。

我最近启动了一个 GitHub 存储库,其中包含适用于 Android 的 Presenter First 示例。由于 Android 架构的复杂性,实现该模式并不简单。视图往往比普通 Presenter First 应用程序中可接受的“胖”,主要是因为活动生命周期和您提到自己的其他怪异。我已经尽力将业务逻辑与平台分离,但肯定还有改进的余地。您可以在以下位置找到示例:

http://github.com/olerass/presenter-first-android

也许您可以从那里借鉴一些想法?或者更好地贡献你自己的一些。

【讨论】:

    猜你喜欢
    • 2014-10-08
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    相关资源
    最近更新 更多