安卓中的Model-View-Presenter模式介绍

这篇博客详细介绍了安卓中的Model-View-Presenter(MVP)模式,阐述了MVP模式的优势,如简化任务、减少bug、提高测试性。讨论了为何在安卓上使用MVP,包括简化后台任务处理和应对Activity的生命周期问题。文中提供了不使用MVP和使用MVP的代码示例,并推荐了Nucleus库以简化MVP的实现。
摘要由CSDN通过智能技术生成
英文原文:Introduction to Model-View-Presenter on Android 
这是一篇观点比较激进的文章,完全否定了MVC模式在安卓开发的中的意义,认为其是没有任何用处的。这篇文章因为使用了静态变量来定义Presenter,因此在原文的评论部分也受到一些争议。不过我觉得还是从中学到了一些思想。我甚至同意MVC模式在安卓开发的中毫无意义的说法。没有完美的文章。另外关于MVP,还看到了一篇思路更清晰的文章,也准备翻译出来。

这是一篇安卓中MVP模式的详细教程,从最简单的例子到最佳实践。本文还介绍了一个让在安卓中使用MVP模式变得非常简单的library。
它是不是很简单,我们如何才能从中获益?
什么是MVP

.View是指显示数据并且和用户交互的层。在安卓中,它们可以是一个Activity,一个Fragment,一个android.view.View或者是一个Dialog。

.Model 是数据源层。比如数据库接口或者远程服务器的api。

.Presenter是从Model中获取数据并提供给View的层,Presenter还负责处理后台任务。

MVP是一个将后台任务和activities/views/fragment分离的方法,让它们独立于绝大多数跟生命周期相关的事件。这样应用就会变得更简单,整个应用的稳定性提高10倍以上,代码也变得更短,可维护性增强,程序员也不会过劳死了~~。
为什么要在安卓上使用MVP
原因之一: 尽量简单

如果你还没有阅读过这篇文章,阅读它: Kiss原则。- kiss是Keep It Stupid Simple或者Keep It Simple, Stupid的缩写。

.绝大多数的安卓程序都只使用了View-Model架构。

.程序员被绞尽了复杂的界面开发中,而不是解决事务逻辑。

在应用中使用Model-View的坏处是“每个东西之间都是相互关联的”如下图:

如果上面的图解看起来还不够复杂,那么想想这些情况:每个view可能在任意的时间出现或者消失,view数据需要保存与恢复,在临时的view上挂载一个后台任务。

而与“每个东西之间都是相互关联的”的相反选择是使用一个万能对象(god object)。注:god object是指一个对象/例程在系统中做了太多的事情,或者说是有太多不怎么相关的事情放在一个对象/例程里面来完成。

god object过于复杂,他的不同部分无法重用、测试,无法轻易的debug和重构。

使用MVP

.复杂的任务被分割成简单的任务。

.更小的对象,更少的bug。

.更好测试

MVP的view层变得如此简单,在请求数据的时候甚至不需要使用回调。view的逻辑变得非常直接。
原因之二: 后台任务

当你需要写一个Activity,Fragment或者一个自定义View的时候,你可以将所有和后台任务相关的方法放在一个外部的或者静态的类中。这样你的后台任务就不会再与Activity相关联,不会在泄漏内存同时也不会依赖于Activity的重建。我们称这样的一个类为“Presenter”。注:要理解此话的含义最好先看懂第一个MVP示例的代码。

虽然有一些方法可以解决后台任务的问题,但是没有一种和MVP一样可靠。

为什么这是可行的

下面的图解显示了在configuration改变或者发生out-of-memory事件的情况下应用的不同部分所发生的事情。每一个开发者都应该知道这些数据,但是这些数据并不好发现。

                                      |    Case 1     |   Case 2     |    Case 3
                                      |A configuration| An activity  |  A process
                                      |   change      |   restart    |   restart

—————————————- | ————- | ———— | ————
Dialog | reset | reset | reset
Activity, View, Fragment | save/restore | save/restore | save/restore
Fragment with setRetainInstance(true) | no change | save/restore | save/restore
Static variables and threads | no change | no change | reset

情景1:configuration的改变通常发生在旋转屏幕,修改语言设置,链接外部的模拟器等情况下。要知道更多的configuration change事件请阅读:configChanges。

情景2:Activity的重启发生在当用户在开发者选项中选中了“Don’t keep activities”(“中文下为 不保留活动”)的复选框,然后另一个Activity在最顶上的时候。

情景3:进程的重启发生在应用运行在后台,但是这个时候内存不够的情况下。

结论

现在你可以发现,一个拥有setRetainInstance(true)的Fragment并没有带来帮助 - 我们还是要保存和/恢复这种fragment的状态。因此我们可以去掉可保持Fragment的情景,把问题简单化。Occam’s razor.

                                      |A configuration|
                                      |   change,     |
                                      | An activity   |  A process
                                      |   restart     |   restart

—————————————- | ————- | ————-
Activity, View, Fragment, DialogFragment | save/restore | save/restore
Static variables and threads | no change | reset

现在看起来就好多了。我们只需要写两部分代码来实现任意情况下完全恢复应用的状态:

.保存/恢复Activity, View, Fragment, DialogFragment;

.在进程重启的情况下重新开启后台请求。

第一部分我们可以通过常规的Android API方式来实现,第二部分就是Presenter的工作了。Presenter可以记住哪个请求应该被执行,并且在执行期间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值