文章目录
  1. 1. 前言
  2. 2. 我的方案 (Our Scenario)
  3. 3. Android架构 (Android Architecture)
  4. 4. 表现层 (Presentation Layer)
  5. 5. 领域层 (Domain Layer)
  6. 6. 数据层 (Data Layer)
  7. 7. 错误处理 (Error Handling)
  8. 8. 测试 (Testing)
  9. 9. 无码无真相 (Show me the code)

前一段时间一直在研究架构方面的知识,加上公司程序的架构也有一些问题,所以我决定找个合适的时间来写一下Android应用程序架构的文章。

此文旨在描述我的一些架构上观点,以及之前几个月我调查研究的一些架构相关知识。

前言

我们知道想要写高质量的软件是非常艰难和复杂的:不只是满足需求,还需要代码健壮、易维护、可测试以及足够灵活来满足需求增加和改变。上述几点特征正是任何软件需要遵循的方法。

实现好的 Android 应用程序架构代表以下一组生产系统的实践:

  • 独立的架构
  • 可以测试的
  • 独立的UI
  • 独立的数据库
  • 独立其他外部组件

clean_architecture1

上图中可以看到架构有此层,但是实际中不一定是4层。此图只是一个纲要。在开发中我们需要依据依赖规则:只可以外层依赖内层,外层对内层来说是透明的。

为了更好的理解上图含义,下面对上图中的术语作一个简单的阐述:

  • Entities: 程序的业务实体
  • Use Cases: 用例统筹业务实体中数据。
  • Interface Adapters: 适配器接口把来自用例(Use Cases)和实体(Entities)的数据转换为 UI(Frameworks and Drivers)需要的数据。Presenters 和 Controllers 都属于这里。
  • Frameworks and Drivers: 所有的细节:UI、工具、框架等。

通过 这篇文章视频 了解更多解释。

我的方案 (Our Scenario)

我以一个简单的例子开始:创建一个简单的应用,这个应用显示一个来自网络的用户列表,当点击任何一个用户,跳转到此用户的详情页面。

Android架构 (Android Architecture)

通过保持业务逻辑不需要了解外部世界来实现关系的分离,因此,可以不依赖外部元素进行测试。

为了实现关系分离,我建议分三层架构,每层与其他层分离,每层有自己的职责。值得注意的是,每层使用自己的数据模型来保证每层的独立性。如果不在引用中使用一套数据模型,付出的代价将是需要使用数据映射来完成数据变换。关系见下图:

clean_architecture_android

PS: 我没有采用任何第三方的库(除了 JSON 数据解析库GSON和测试库 Junit、Mockito、Robolectric 和 Espresso),这样保证了 Demo 尽量简单。我们平日比较常用能让我们开发更简单的 orm 框架、依赖注入框架以及其他的工具或三方库都没有使用。“重复发明轮子是非常不建议的”

表现层 (Presentation Layer)

这一层主要是控件逻辑相关和动画展示。这层实现不仅限于 MVP,还包括其他的模式,比如 MVC 或者 MVVM。这我不再赘述。Fragments 和 activities 只是用来显示和 UI 逻辑以及渲染,没有任何逻辑操作。

在这一层 Presenters 是由各种 interactors (use cases) 组成的,他们负责执行一个异步任务,并通过回调取回需要的数据给UI渲染。

presentation layer

如果你想看一看一些比较酷的 MVP、MVVM 例子,可以参考 Effective Android UI 。

领域层 (Domain Layer)

所有的业务逻辑都是在这层处理的。考虑到 Android 工程,你会看到所有的 interactors (use cases) 也是在这里实现的。

这层是一个纯 Java 的模块,不包含任何 Android 依赖,所有的外部交互都是通过接口来实现。

domain layer

数据层 (Data Layer)

所有 App 需要的数据都是通过这层的 UserRepository (实现了 DomainLayer 的接口)提供的,它使用了 Repository Pattern 的策略—— 通过一个工厂,根据不同的条件抓取不同的数据源。比如,当通过 id 来获取一个 user 时,如果这个 user 在缓存中不存在,那么它会选择磁盘缓存作为数据源,如果磁盘缓存也不存在它会通过云端接口获取数据,并保存在本地缓存中。

这个理念的核心是数据源对于 Client 端来说是透明的,Client 端不需要关心它是从内存、磁盘或者云端拿到的数据,它只知道这样可以拿到数

data layer

PS: 在代码方面,我实现了一个简单的基于文件和 SharedPreference 的磁盘缓存(仅为演示)。你可以替换为任何好用的第三方缓存库,注意永远不要重新发明轮子。

错误处理 (Error Handling)

这是一个值得讨论的话题,非常欢迎任何分享。我的策略是实用回调机制。如果 DataRepo 发生变化,回调接口提供两个方法:onResponse() 和 onError(), 后者把错误封装在 ErrorBundle 类里面:这种处理方式带来一个问题,错误通过层层传递(就是异步编程中常见的 CallbackHell 问题 )导致代码可读性变差。

或者可以使用 EventBus 来处理,但是这种方式有点像 GOTO 会导致代码逻辑混乱。

测试 (Testing)

至于测试,对于每层我采用了不同的方案:

  • Presentation Layer 使用 AndroidInstruction 和 espresso 做集成测试和功能测试
  • Domain Layer 使用 JUnit 和 mockito 做单元测试
  • Data Layer 使用 Robolectric(这层有 Android 依赖)和 junit、mockito做集成和单元测试。

无码无真相 (Show me the code)

Android-CleanArchitecture (Github)

原文地址:Architecting Android…The clean way?


本文地址 http://94275.cn/2014/09/12/architecting-android-applications/ 作者为 Zhenguo

author:Zhenguo
Author: Zhenguo      Blog: 94275.cn/     Email: jinzhenguo1990@gmail.com
I have almost 10 years of application development experience and have a keen interested in the latest emerging technologies. I use my spare time to turn my experience, ideas and love for IT tech into informative articles, tutorials and more in hope to help others and learn more.
文章目录
  1. 1. 前言
  2. 2. 我的方案 (Our Scenario)
  3. 3. Android架构 (Android Architecture)
  4. 4. 表现层 (Presentation Layer)
  5. 5. 领域层 (Domain Layer)
  6. 6. 数据层 (Data Layer)
  7. 7. 错误处理 (Error Handling)
  8. 8. 测试 (Testing)
  9. 9. 无码无真相 (Show me the code)
返回顶部