我最近开始构建一个 android 应用程序,我想从头开始使用设计模式。有人告诉我 MVP(Model-View-Presenter)是 android 应用程序的一个很好的模式。
我想知道是否可以实现 MVP 模式的“被动视图”变体?如果可以的话,我会显示任何代码.. 但现在我不知道被动视图在 android 应用程序中应该是什么样子。另外..在被动视图场景中哪个角色会扮演 MainActivity?
我将不胜感激有关如何实现被动视图的任何解释、教程或示例。
我最近开始构建一个 android 应用程序,我想从头开始使用设计模式。有人告诉我 MVP(Model-View-Presenter)是 android 应用程序的一个很好的模式。
我想知道是否可以实现 MVP 模式的“被动视图”变体?如果可以的话,我会显示任何代码.. 但现在我不知道被动视图在 android 应用程序中应该是什么样子。另外..在被动视图场景中哪个角色会扮演 MainActivity?
我将不胜感激有关如何实现被动视图的任何解释、教程或示例。
我有一种感觉,这里对主持人有一个致命的误解。尽管 MVP 是通用标准,但大多数人认为 Presenter 是控制器,或者更糟糕的是控制器、存储库、网关的组合。
演示者应该做一件事:演示。这应该是它的唯一目的。许多人在不知不觉中实现了一个 MVC 架构,称之为 MVP,并限制数据流如下:View <-> Controller / Presenter <-> Model.. 现在这种模式没有任何问题,因为它分离了系统的各个层,如果正确完成。您应该能够将域和数据层(Android 开发人员通常将这些层称为 Presenter 和 Model 层)交换到另一个系统,并且代码应该仍然可以正常工作而没有任何依赖性问题。要实现这一点,您必须避免任何会导致绑定到所谓的细节(UI、数据库、框架、硬件、浏览器、操作系统)的依赖项。现在说到层,我们通常会有这样的数据流层次结构:UI -> 域 -> 在 Android 应用程序中,我们会将所有 UI 代码放入 UI 组件中的数据。现在有 2 个选项来定位演示者: 您可以通过为演示者特定视图引入接口来抽象视图。避免演示者中的任何 android / 硬件特定依赖项(如上下文)。如果您实现了这一点,那么您可以说,您的 Presenter 属于您的域层。如果您的 Presenter 知道任何 Android 细节(或者更糟糕的是数据库),那么您会自动将其放入 View 层(如果您尝试从中访问数据库,甚至会破坏您的架构)。现在让我们假设你抽象了你的 View 并且你的 Presenter 是一个 Domain 对象。您的 Presenter 不再关心其代表视图的实际实现,它有它的抽象,它知道将值传递到哪里。无论是移动、Web 还是嵌入式应用程序都不再重要。现在 Presenter 如何从数据层接收数据并用数据填充 UI?我们使用与视图相同的技术:抽象。我们将创建存储库、网关、数据服务的接口/抽象类,或者您想调用数据/模型层的接口。您将拥有 POJO、您的数据访问逻辑、缓存等。请注意,到目前为止,我们正在使用 POJO!我们不依赖任何平台绑定细节(如上所述)。但是由于我们现在需要做一些缓存,我们必须使用 Android(或 Room)中的 SQLite 管理器。这个怎么做?抽象。抽象任何导致您的代码绑定到任何平台的细节。网络或嵌入式应用程序不再重要。现在 Presenter 如何从数据层接收数据并用数据填充 UI?我们使用与视图相同的技术:抽象。我们将创建存储库、网关、数据服务的接口/抽象类,或者您想调用数据/模型层的接口。您将拥有 POJO、您的数据访问逻辑、缓存等。请注意,到目前为止,我们正在使用 POJO!我们不依赖任何平台绑定细节(如上所述)。但是由于我们现在需要做一些缓存,我们必须使用 Android(或 Room)中的 SQLite 管理器。这个怎么做?抽象。抽象任何导致您的代码绑定到任何平台的细节。网络或嵌入式应用程序不再重要。现在 Presenter 如何从数据层接收数据并用数据填充 UI?我们使用与视图相同的技术:抽象。我们将创建存储库、网关、数据服务的接口/抽象类,或者您想调用数据/模型层的接口。您将拥有 POJO、您的数据访问逻辑、缓存等。请注意,到目前为止,我们正在使用 POJO!我们不依赖任何平台绑定细节(如上所述)。但是由于我们现在需要做一些缓存,我们必须使用 Android(或 Room)中的 SQLite 管理器。这个怎么做?抽象。抽象任何导致您的代码绑定到任何平台的细节。现在 Presenter 如何从数据层接收数据并用数据填充 UI?我们使用与视图相同的技术:抽象。我们将创建存储库、网关、数据服务的接口/抽象类,或者您想调用数据/模型层的接口。您将拥有 POJO、您的数据访问逻辑、缓存等。请注意,到目前为止,我们正在使用 POJO!我们不依赖任何平台绑定细节(如上所述)。但是由于我们现在需要做一些缓存,我们必须使用 Android(或 Room)中的 SQLite 管理器。这个怎么做?抽象。抽象任何导致您的代码绑定到任何平台的细节。现在 Presenter 如何从数据层接收数据并用数据填充 UI?我们使用与视图相同的技术:抽象。我们将创建存储库、网关、数据服务的接口/抽象类,或者您想调用数据/模型层的接口。您将拥有 POJO、您的数据访问逻辑、缓存等。请注意,到目前为止,我们正在使用 POJO!我们不依赖任何平台绑定细节(如上所述)。但是由于我们现在需要做一些缓存,我们必须使用 Android(或 Room)中的 SQLite 管理器。这个怎么做?抽象。抽象任何导致您的代码绑定到任何平台的细节。DataService 或者您想调用数据/模型层的接口。您将拥有 POJO、您的数据访问逻辑、缓存等。请注意,到目前为止,我们正在使用 POJO!我们不依赖任何平台绑定细节(如上所述)。但是由于我们现在需要做一些缓存,我们必须使用 Android(或 Room)中的 SQLite 管理器。这个怎么做?抽象。抽象任何导致您的代码绑定到任何平台的细节。DataService 或者您想调用数据/模型层的接口。您将拥有 POJO、您的数据访问逻辑、缓存等。请注意,到目前为止,我们正在使用 POJO!我们不依赖任何平台绑定细节(如上所述)。但是由于我们现在需要做一些缓存,我们必须使用 Android(或 Room)中的 SQLite 管理器。这个怎么做?抽象。抽象任何导致您的代码绑定到任何平台的细节。
您可以在下面看到 Bob 大叔提出的可靠软件架构设计的图片。内层不应该有外层的任何知识。这张图反映了我刚刚在这里描述的开发技术,这与 Bob 大叔的书中描述的技术相同。我们通过使用它们的抽象来避免对细节的任何依赖。真正的实现(Activity、Fragments、SQLiteDatabase)通过依赖注入从外部“连接”到内层。这种技术也称为依赖倒置。
我建议您阅读 Robert C. Martin 的《清洁架构》一书,以加深对它的理解。
Android 中的 MVP 模式建议您的视图类(片段、活动)不包含任何表示或业务逻辑,但所有逻辑都委托给 Presenter 类。void
当 View 初始化、事件发生或 View 被销毁时,Presenter 通常会调用View 提供的方法。
所以想象一个 View 和一个 Presenter 实现以下接口:
public interface Contract {
interface View {
void initView();
void setTextColor();
}
interface Presenter {
void init();
void onButtonClicked();
}
}
在我们的简单示例中,视图将初始化 Presenter(依赖注入超出了本文的范围),然后调用 Presenter 的initView
方法。Presenter 将负责所有初始化逻辑,例如从网络/存储中获取数据,并在需要时更新视图。当用户依次单击按钮时,View 将通过调用 Presenter 的onButtonClicked()
方法将操作委托给 Presenter。Presenter 可以做一些处理,根据结果可能会调用 View 的setTextColor()
方法。
使用 MVP 的最重要原因是能够使用 Junit 和 Mockito 之类的模拟框架测试您的逻辑。您的 Presenter 应该用纯 Java 或 Kotlin 编写,而不依赖于 Android 框架库。然后,您可以使用 JVM 测试您的 Presenter,而无需连接设备。这都是 Bob 大叔清洁架构指南的一部分。
MVP 的两个最佳资源是 Antonio Leiva 的博客文章和 Google 在github中的架构示例
与 MVP 合作并不难
首先,在包 Model 中,您将存储所有类型的 POJO 类,这些类具有 setter、getter 和应用程序的所有数据结构
然后是演示者,您可以在其中绑定这些对象并对其执行一些逻辑。
在演示者中完成所有逻辑之后,它将所有这些信息传递给视图,因此之后您的 MainActivity(在本例中为视图)将只有几行代码,并且您的代码看起来非常有条理。
至于被动视图,这意味着您拥有的视图代码更少,将来可以运行测试并拥有可维护的代码。
你可以使用 MVC、MVP、MVVM,但如果你想开始,我建议你从 MVP 开始
看看这张MVP的图片
您还可以查看有关 MVP 的本教程