本文是对Antonio Leiva关于MVP的一篇博文的中文翻译。查看原文可点击这里
翻译加入了一些自己的理解,如有不妥之处,希望大家指正。以下是原文翻译:
MVP(Model View Presenter)模式衍生自著名的MVC(Model View Controller)模式。
MVC长一段时间都在Android应用开发中占据着重要的地位。
现在由越来越多的人谈论MVP,却鲜有可靠而组织化的资料。
因此我想要通过这篇博文来促进大家的讨论,并让大家将所学的知识尽可能最优地应用到我们的项目中,
什么是MVP?
MVP模式将表示层从逻辑层分离,这样一来,就把 内部接口如何工作? 和 我们怎样将接口处理的结果展现到屏幕上? 进行了分离。
概念上来说,MVP模式可以让同一套逻辑拥有完全不同的可交替的界面。
首先需要阐明的一点是,MVP不是架构模式,它仅仅负责表示层。任何情况下,在你完全没有使用MVP的架构中加入MVP总是件好事。
为什么要使用MVP?
在Android开发中,我们不得不面对一个严峻的事实:Activity高度耦合了用户接口和数据获取机制。甚至还能找到像CursorAdapter这样的极端例子。
这个例子中,CursorAdatper将Adapter(可认为是View的一部分)和 cursor(可认为属于数据访问层)整合到了一起。
为了能够轻松地扩展和维护一个应用,我们需要定义良好分离的层次结构。如果明天我们不再从数据库获取数据,而必须从web服务器上获取数据,
我们该怎么办呢?如果各个层次都高度耦合的话,我们就只能重写整一个view了。
MVP将view从我们的数据源独立出去。我们将应用分为至少三层,这样我们可以分别对它们进行测试。通过MVP,我们可以将大部分有关业务逻辑的方法从
Activity中移除,因此我们讲可以在不使用instrumentation tests的情况下对其进行测试。
如果实现Android中的MVP?
好吧,从现在开始,问题就变得有点模糊不清。实际上,存在着很多的MVP实现变体,任何人都可以根据他的想法将MVP调节成他所喜欢的形式。
这些不同基本上取决于我们委派给Presenter的任务数量。
到底是该由view来负责启用或禁用一个进度条,还是该由presenter来负责呢?又该由谁来决定action bar应该显示什么动作呢?这就是抉择v开始的地方。
我将会向你展示我常用的方法,但我也希望这篇文章成为讨论MVP详细实现规范的地方,因为到目前为止,还不存在一套“标准”的方式来实现它。
The Presenter
Presenter负责担任view和model之间的中间人。它从model取回数据,并将其格式化后返回到view中。
和传统的MVC模式不同,Presenter还决定了当用户和view进行交互时该如何响应。
The View
View通常是一个Activity(也可以是一个Fragment,一个View,这取决于App的结构),它包含了一个对Presenter的引用。
理想情况下,Presenter是通过依赖注入的方式提供的(比如通过Dagger),但如果你没有使用这类工具,也可以直接创建一个Presenter对象。
View需要做的唯一一件事就是:当有界面动作发生时(比如一个按钮被点击了),调用Presenter中的相应方法。
The Model
在一个拥有良好的层次结构的应用中,这里的Model指的是与域层(domain layer)或者业务逻辑层进行交互的唯一途径。
如果我们使用的是鲍勃大叔的整洁架构(Uncle Bob clean architecture),
Model这时候也许就是一个实现了一个用例的交互器(interactor),不过这又是另外一个话题了,我想我会在以后的文章中讨论它。
现在,将Model看做是一个给View提供数据(用于界面展示)的提供者就足够了。
一个例子
由于字面解释过于冗长,我在github上创建了一个实例。
实例包含了一个登录界面,该界面用于验证登录信息,然后让用户访问主界面。主界面包含了一个从Model中获取数据的列表。
这篇文章并没有解析例子中的任何的代码,因为这十分简单。但如果你发现其中有理解困难的地方,我会新写一篇文章来对其进行详细的解释。
总结
在Android上将接口和逻辑分离并不简单,但通过MVP模式,我们可以更容易地防止Activity退化成高度耦合的、包含了成百上千行代码的类。
在大型应用开发中,将代码组织好是很有必要的。否则,对代码的维护和扩展都会变得不切实际。