本系列文章旨在概述咱们搭建 Android 应用程序架构时可能会碰到的问题。我意识到,不管实现 Android app 架构的过程多么困难,结果证实这些必定是完成每个卓越的应用的基础。java
每种技术都有其天然的进化。或者更确切地说,它的社区经历了进化的过程。一个新的计算机语言或框架的早期采用者是爱好者,他们只是但愿掌握技术,并尽快完成一些工做。一般,新社区规模小,在开发人员之间的知识传递潜力有限,也就是说,每一个人都从本身的错误中学习,由于没有架构指南可用。android
你能够说,有不少资深的家伙在不一样的技术上有不少的经验,但谁也没有时间提出标准。嗯,不必定。若是技术背后有一个强大的公司期望赚钱,他们的布道师会告诉你这个新语言多么酷,能够作不少事情,容易学习,可扩展,而且能够知足数以百万计的用户。程序员
微软就常常用它的技术干这样的事情。另外一方面,当谷歌收购了 Android, 我真的觉得他们只是把它看成一个可有可无的项目。 若是你从 Android 诞生之时就进入 Android 的世界,你必定记得 Google 根本不在意你的那种沮丧感。 那些有额外的经验,能力和帮助社区的意愿的少数几我的如今是 Android 的超级明星或大神 —— 譬如 Jake Wharton。数据库
“When Google bought Android, I honestly think they treated it just as some other side project.”编程
可能你会说,你没必要考虑太多架构和组织代码的事情,由于(Android)Framework 帮你作了。Android 强迫你把界面放到 Activity 中,可重用的界面放到 Fragment 中, 后台服务放到 Service 中,而且用 Broadcast Receiver 和其它组件通讯,这样可使你的生活变得更美好,是这样吗?不是的。网络
首先,有一些很好的实践和原则确实很好,与技术(平台)无关。例如,单一职责原则,依赖倒置原则,面向接口编程,杀死全局状态,尝试消灭全部状态,等等。架构
Framework 不多强迫你遵循原则。偏偏相反,它们以最坏的方式侵犯这些最佳实践和原则。想一想 Context 这个你处处使用的上帝对象(God object),各类单例管理者(singleton managers),拥有生命周期的 Fragment(那是怎样的噩梦呢),经常不能正确实现的 AsyncTask,它们吸着你 app 的血。app
一个缺少指导的刚入行的开发者很容易造出一个怪物而不是一个 app。把它想象成一个意大利面条般的怪物吧 —— 这是一个不错的怪物,但不是一个好的 app。框架
译者注:意大利面条般的怪物寓指一团乱麻的代码ide
最后,技术(technology)和 Framework 隐藏了 app 的用途。好的,这是一个 Android app,可是一个什么样的 Android app 呢?新闻阅读器?音乐播放器? 语言学习程式?天气应用?也许是一个计划表。若是全部的东西都打包到由 Framework 提供的类,你就说不出(这是什么 app)。
正如 Robert Martin,也就是 Uncle Bob 说,“你的架构应该尖声喊出(scream)app 是作什么”,更技术一点说,业务逻辑应该清晰地分离,独立于 Framework。
我但愿已经说清楚了,你不该当依赖 Framework 来使你的代码整洁有序,尤为是在编写 Android 代码的时候。咱们很早之前就意识到这点,但是缺少拿出牛逼解决方案的经验。架构失败要花不少时间才能表现出来,又不能够在项目中途改变整个架构。也不可能有时间将旧项目重构成新的、酷的、(想成为)最佳的架构。所以,咱们采起渐进的方法,慢慢地从一个项目到另外一个项目搭建咱们的架构,从咱们的错误中学习。咱们认为咱们的架构应该知足几个目标,它们是检验咱们的方法的标准。好的架构应该作到:
利益相关者(在这篇文章中)是任何对你的 app 开发感兴趣的人。除了开发,还有视觉设计师,交互设计师,项目经理,数据库管理员,测试等等。
固然,你不可能以某种方式组织你的代码,例如,交互设计师能够打开项目并当即了解全部内容,甚至能够进行一些修改。It's a unicorn.
个人意思是,你能够以这样一种方式组织你的代码,那个和交互设计师对接的程序员只须要打理和交互相关的代码。所以,全部交互被分离到那些负责交互的 classes / modules / components / whatever (组件)中,当处理 app 的交互部分时,只须要打理那些组件。
译者注:若是暂时不能理解利益相关者,不要紧的,看完本系列第三部分你就明白了
我刚刚所说的就是一个关注点分离的例子。咱们支持这种特定的方法,由于它能很好地表达团队组织和项目阶段的配合,通常来讲,你的架构也应该支持关注点分离。关注点分离或者单一职责原则是指,每个组件应该只有一个变化的缘由。
逃离真实世界这条规则,先前已经说起。咱们曾说咱们想要尖声喊出 app 真正是作什么的,就是那样。咱们想要强调业务逻辑而且隐藏 Framework 的细节。这条规则应该更严格:不只要隐藏 Framework 的细节,并且要隐藏全部与外部世界相关的细节。
全部的肮脏的 Android 的东西,如传感器、通知机制、屏幕细节、数据库访问、互联网访问等。
你应该尽量地对你的 app 进行单元测试,而且你的架构应该容许你这样作。若是你不能测试全部东西,你至少应该覆盖你的业务逻辑。与真实世界分离能够很方便地作到这点。若是你的业务逻辑清晰地和 app 其他部分隔离,是很容易测试的。
public final class UsersActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
new ListUsers().execute();
}
private final class ListUsers extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
// final SQLiteOpenHelper sqLiteOpenHelper = ...
// JsonObjectRequest jsObjRequest = new JsonObjectRequest
// (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
// MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);
// showData(user);
return null;
}
}
}
复制代码
你可能在 “上古时代” 看到过这样的代码。若是没有,说明你很年轻。可是这一段代码哪里有问题呢?答案是哪里都有问题。
咱们有一个 Activity 操做数据库,访问网络,解析数据,切换线程以及渲染数据。全部的利益相关者都在看这一个类,没有关注点是分离的,它是不可测试的,业务逻辑和 Android 的东西混杂在一块儿。
译者注:留意上图左边红色的标签。每一个标签分别对应一条黄金法则,红色表示不知足。SRP 是指单一职责原则,即分离关注点。
第一种方法显然是不能工做的。咱们尝试过的第一件事情是 MVP,或者说 model-view-presenter。每一个人都熟悉 MVP。它是最受欢迎的架构模式之一。看起来像这样:
这里,咱们分离了其实是 Android Fragment 的 View,咱们拥有表明咱们业务的(领域)模型,最后咱们有协调一切的 Presenter。这确定是更好的。关注点有了一些分离,利益相关者再也不那么困惑,你也能够写一些单元测试了。尽管如此,因为 Presenter 直接操做数据库和全部一切,咱们仍然和真实世界混杂在一块儿。Presenter 成了上帝对象。它处理模型,将数据发送到视图,它拥有业务逻辑(业务逻辑是那些齿轮 :)),它访问数据库和网络,获取传感器数据,等等。因此,是好了些,但能够更好。
译者注:黄色的标签表示好了些
当政府不知道作什么的时候它会作什么?它成立一个代理机构。当开发不知道作什么的时候他们会作什么?他们引入一些 Manager。你不必定把它命名为 “*Manager” 。 这些类有不少名字:uitls、helpers、fooBarBuzz-ator、等等。所以咱们引入 Manager。
说实话,这甚至有点凑效。业务逻辑包含在 Manager 中。利益相关者知道往哪看,关注点必定程度是分离的但能够作得更好,你能够编写更多的测试,但你依然直接触摸 Android ,因此你必须编写 Android 测试用例,并预先填写数据库来测试业务逻辑,一个字:不爽。是的,Manager 有变成巨兽的倾向,很快就变得难以维护。你可能争论说它不会变得更复杂,你能够经过更简单的架构来更快地提供代码,但经过这种方法依然会有不少 BUG,可维护性也会遭到破坏。
译者注:留意 Manager this 和 Manager that 之间的标签
在本系列的第一部分,咱们经历了搭建实际可用的 Android 架构的挑战。良好的 Android 架构应该知足众多利益相关者的需求,支持关注点分离,强调业务逻辑,隐藏 Framework 的细节,并使你全部的组件均可以测试。在系列的第二部分,咱们将向你展现咱们如何管理对咱们有用的功能。在此以前,你是否有如何建立合适的 Android 工做流的建议?或者你遇到了什么问题?