MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 web 应用程序的模式。其分层有助于管理复杂的应用程序,因为可以在一个时间内专门关注一个方面。例如,可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。

android mvc搭建 安卓mvc_android mvc使用方法

想在你的 Android 应用里优雅地分离出应用状态、用户交互和数据表现吗?

一个开发平台的设计者是的不会有闲工夫为你量身打造一个高层的应用架构的。但是你恰恰可以利用这一点,充分利用你的自由,根据应用需求和规模来实现你自己的架构。如果你仅仅要做些简单的小玩意儿,那么好吧,你可以随意在你的 widgets(像 text fields、spinners 之类的)中存储数据,然后就在诸如 OnClickListener 中去操控它们。可是话又说回来,如果你要写些宏伟的应用,或者想让你的小玩意儿更丰富迷人一点呢?那你还是考虑考虑分个层吧,因为一个好的架构会鼎力支持你去添加新特性,满足你梦寐以求的高性能、高灵活性、高度响应性等等需求。当然,你的代码也会因此摆脱蓬头垢面心乱如麻的糟糕状态,从此过上幸福的生活……

好吧,说正经的。在接下来的几分钟的光阴里,我将带你看一看如何根据大名鼎鼎的 MVC,来把你的代码大卸三块。三块之间还是藕断丝连的,比如我会告诉你怎么用 Android 的 messaging 框架,来把 view (V) 和 controller (C) 连一连。我把这一实践应用到我自己的代码中,也许它并非 100% 的符合学术标准,也可能不是对每一个 app 都能成为天作之合,但是当我的应用变得越来越庞大的时候,我还是很享受它所给我带来的好处的。

android mvc搭建 安卓mvc_android mvc搭建_02

简介

关于这个 MVC,我就不多说了吧,到处都可以找到它的“广告”。我也不介意你到我写的 里面看一看。你最好先了解了解 Model,View,Controller 这三个东西。另外呢,如果你还没有看过 ,最好还是去看看吧。尽管这篇文章里没有完整描述 messaging 这朵奇葩,你还是可以在里面打听到一些关于线程模型的八卦。接下来我会一直带你绕着一个样例转一转,转到最后你会看到样例的源代码。

Part 1: Model

把 Model 层泛化,并且让它只能接触到主逻辑,这是一个不错的开端。我们的样例看起来其实是一目了然加了无趣味,但还是有些有趣的地方。首先,我们有一个单独的类来包含 model 的“数据”——指的是,在应用的生命周期中, Model 层内可能发生变化的各种状态。

android mvc搭建 安卓mvc_android mvc使用方法_03

呃,你没有看走眼,我的确喜欢加个标注叫 @Immutable,这样一来我就会铭记这个类事实上是永恒不变的。这样有很多好处,比如说我能够在线程之间共享一个类的实例。另外,我还让这个类 Serializable,这样可以允许我实现一些例如 “Save/Load” 之类的特性。

至于 Model 类本身,它长成这个样子:

android mvc搭建 安卓mvc_android mvc使用方法_04

android mvc搭建 安卓mvc_MVC_05

方法 updateData() 要花一点时间来执行,在真实世界里,它可能是在请求服务器、执行繁重的计算等。data 被 synchronized 好好地保护了起来,不会被并发地访问。Listeners 也能安全地从并发线程中被添加或删除。如果你已经和 MVC 有过交往,你会意识到 model 的 listeners 是这个模式的中坚力量——它们让你能把任何代码附加到 model 上,而 model 却对此一无所知(因此 model 的代码就可以免受任何不相干的逻辑注入的伤害)。

现在来看最有意思的部分——Controller 层。

Part 2: Controller

其实吧,你可以通过很多种方式实现 Controller 这一层。 我选择的方式是基于 Handler, HandlerThread 与 Message 类的方法。当然,你多少要懂点它们的工作方式。

说到底,Android 平台让你可以通过这几个类来实现应用中各部分之间高效、安全且强大的 messaging 通信。在我们的例子里,我想做的的东西是:

送给 Controller 一个 inbox handler——这样 View 层就能给他写信(message)了,信的内容可以是“用户让我退出”或者“用户让我更新这些数据”以及其它一些甜言蜜语。

送给 Controller 一个或多个 outbox handlers——这样 Controller 就也能给 View(或 Views,比较多情,你懂得)写信(message)了,比如“ model 已经更新完了”或者“你自杀吧,我要退出了”,等等。

通过这样的方式,View 只能把用户事件装在信封(message)里寄给 Controller,并不用自己决定怎么对用户事件进行反应。一旦 Controller 给 View 寄来一封信(message),View 就会无脑地处理 Controller 告诉她的事情,并且给用户呈现出一些应用的状态。

通过这样一个悲情的故事,我们很干净地就实现了 MVC 的架构,虽然有点不太仁义。

由于 Handler 需要一个 Looper,我们需要选择一个线程,来运行 Controller 的 inbox handler。我们可以选择在 UI 线程中(它既能处理 UI 消息,又能处理 Controller 的消息)或者一个新的单独的 HandlerThread 中来运行。通常我们的 Controller 不会被困在一个很慢的操作中处理它的消息,这样它才能即使对 View 作出相应。所有很慢的操作都会在后台线程中运行。因此我们可以放心让

UI 线程来处理 Controller 消息。但是我还是选择运行一个单独的线程,仅仅是因为这样看起来架构会比较干净,也可能因为这样 Controller 的响应会有一点点的更快吧。既然 messageing 框架帮助我们摆脱了并发问题的牢笼,我们可以不用修改大量代码,就轻易地从一个 solution 跳到另外一个。

来看看我们管理 inbox handler 和 outbox handler 的代码:

android mvc搭建 安卓mvc_MVC_06

android mvc搭建 安卓mvc_Android_07

这些并不是 Controller 的完整代码。先说点其它的我们马上回来。你现在能看到的是我们如何初始化 inbox handler 与它的线程,如何提交一个 handler 到 outbox handlers 中去,以及如何用一个消息通知所有的 outbox handlers。

有了这些代码,我们可以得到 inbox handler,并可以从 View 层向它发送消息,同时我们有绑定了 View 的 outbox handler,能够让 Controller 与它的 Views 有效地交换异步消息。

为了能处理收到的消息并做点什么,我们需要在 Controller 类中实现 handleMessage() 方法。在大部分应用中,你都可能想在这里实现一个设计模式中的状态模式的实例,因为根据应用正在处理的工作的不同,我们可能需要对一个消息进行不同的处理,乃至忽略一些消息。例如,在我们的应用中,一旦你开始刷新模型了,你肯定不希望用户在刷新完成之前再刷新一次。为了表明这一点,我给出了 ControllerState 接口和它的 ReadyState 的实现:

android mvc搭建 安卓mvc_android mvc使用方法_08

android mvc搭建 安卓mvc_应用程序_09

把 Controller 和它的状态们(stages)放到同一个 package 中,我们可以让它们使用默认访问级别就能访问到 Controller 的内部。我就不把 UpdatingState 的代码贴这儿了,在页底的附件中都有。

这里看看 Controller 是怎么把消息处理委托给它的 state 的:

android mvc搭建 安卓mvc_android mvc使用方法_10

android mvc搭建 安卓mvc_android mvc使用方法_11

好了,Controller 大概就是这般模样,现在让我们介绍个 View 给它认识认识吧。

Part 3: View

不用过多解释了,我猜你已经知道怎么做了。上代码(DemoActivity):

android mvc搭建 安卓mvc_Android_12

android mvc搭建 安卓mvc_MVC_13

android mvc搭建 安卓mvc_应用程序_14

在这一样例中,Activity 实际上占据了 Controller 的实例,而这个 Controller 是控制着 model 的。然而,如果你觉得 Service 的生命周期更能匹配 Controller/Model 的生命周期的话,你也可以考虑把 Controller 转移到一个 Service 中。

总结

你现在应该很清楚了,基于 message 的方法的的确确能允许我构建一个强大的、复杂的 Controller 与一个完全百依百顺的贤惠的 View。这样我们就有了一个很好的 MVC 的实现。

正如我在开头所写的那样,这一解决方案从理论上讲不一定完全有效,也不一定就适合你的 app,但是我已经经历了构建一个非常复杂应用的过程,这中间有很多种状态,并且它完全依赖于消息。这一架构会有很多弱点,比如你要在某个地方聚合 message 的代码(见ControllerProtocol)并在文档里定义很多 message 参数。但是别忘了好处:它很好地实现了层间的分离,当你的 app 越长越大时,你更会体会到这一框架的美妙。

mvc设计模式详细分析到这基本交完了,主要是通过简单的文字和详细的代码来介绍了MVC的三部分,分别是Model(模型)、View(视图)和Controller(控制器)。