Architecting Android…The clean
way?


过去几个月,与@pedro_g_s 和 @flipper83 (顺嘴说一下这两位是android开发大牛)两位同行在Tuenti 站点上友好的讨论之后。我觉得这是一个写一篇关于android应用架构的文章的好时机。

写这篇文章的目的是想给大家展现一些我在这几个月所想的加上从研究和实施中学到的一些小方法。

入门指南

我们知道写一款有品质的软件是困难和复杂的: 不仅要满足要求,同一时候也是健壮的、可维护的、可測试的。并且足够灵活适应扩展和变化。这时 “清晰架构” 就出现了,并且可能是一个开发不论什么软件应用的好方法。

这个思路非常easy:清晰架构表示产品系统遵循一组实践原则:

  • 框架独立.
  • 可測试性.
  • UI独立.
  • 数据库独立.
  • 不论什么外部代理模块独立.

不一定非要使用四环结构 (如图所看到的),由于这仅仅是一个原理图,可是你应该考虑依赖原则: 源代码依赖仅仅能向内指向,而且内核中的全部项不能了解不论什么外环的东西。

下面是一些相关的词汇用一个更好的方式熟悉和理解这些方法:

  • Entities: 应用的业务对象。
  • Use Cases: 结合业务对象的数据流入流出的用例. 相同被称为Interactors。

  • Interface Adapters: 这组适配器以最合适的格式转换用例和业务对象之间的数据。Presenters(表现层) 和 Controllers(控制层)就属于这里。
  • Frameworks and Drivers: 这里是详细的实现:UI。工具类, 框架,等等。

想要更好更生动的解释,參考这篇文章 或 视频

我们的场景

我会用一个简单的情景让一切開始:创建一个简单的APP用来显示从云端获取的朋友列表和用户检索。当点击它们的时候。一个新的界面为用户显示具体信息。

我放了个视频在这里。这样你对我所说的有个大概的映像:

Android 架构

目标是 分离关注点。让业务规则对外环事物一无所知,因此,它们在被測试时不须要依赖其他外部元素。

要实现这个目标,我的 建议是将项目分为三层,每个都有自己的目的而且和其他层分开工作。

值得一提的是,每一层都有自己的数据模型以达到这样的独立性(你会在看到在代码中须要一个数据映射来完毕数据转换,这须要付出一点代价,假设你不想把你的模型和整个应用交叉使用)。

这是图示,你能够感受一下:

注意: 我没有使用不论什么外部库(除了用于json数据的解析的gson和用来測试的junit、mockito、robolectric 和espresso)。 原因是它能够使这个样例更清晰。

不管怎样不要犹豫加入ORMs存储数据、依赖注入框架或者你熟悉的不论什么类库,这些都会让你变得更轻松。(记住反复造轮子是不明智的)。

Presentation Layer (表现层)

在这里, 表现的是逻辑和视图动画的关联。 这里用了一个Model
View Presenter (下称MVP)。可是你也能够用其他不论什么模式。像MVC
或者 MVVM。 我不会在这里具体描写叙述它们,可是这里 fragments and
activities 不过views,它们内部除了UI逻辑没有其他逻辑, 这也是全部渲染发生的地方。

在这层的Presenters 由多个 interactors
(用例) 组成,在android UI线程之外的新线程运行job,并通过回调将要渲染到view的数据取回。

假设你须要一个使用MVP或者MVVM Effective
Android UI
 的炫酷的样例,能够看看我的朋友 Pedro Gómez 所做的。

Domain Layer (领域层)

业务规则定义:全部的逻辑发生在这一层。 对于android项目,你也会看到全部的 interactors (用例) 在这里实现。

这一层是一个纯java的模块,没有不论什么android依赖。

全部的外部组件使用接口訪问业务对象。

Data Layer (数据层)

应用须要的全部数据来自这一层,通过UserRepository实现(这个接口在 domain layer),使用了 Repository
Pattern
作为策略, 通过一个 factory 类,依据一定条件下选择不同的数据源。

比如: 通过ID获取用户时。假设这个用户在缓存中已经存在。则硬盘数据会被选中,否则 会从云端获取数据并保存在本地磁盘。

这一切背后的理念是数据源对client是透明的。 client不关心数据来源于内存、磁盘或者云端。它仅仅关系数据会到达和被获取到。

注意: 出于学习的目的,这里我实现了一个很easy的代码,使用文件系统和android preferences 实现原始磁盘缓存,再次,假设已经存在能出色完毕这些工作的类库,SHOULD
NOT REINVENT THE WHEEL(不要反复造轮子)。

Error Handling (错误处理)

这是一个长期值得讨论的主题。假设你能够分享你的解决方式那真实太好了。

我的策略是使用回调callbacks, 因此。 假如数据仓库发送改变。回调callback有两个方法 onResponse() 和onError(). 最后封装异常的类叫 “ErrorBundle”: 这样的方法会带来一些困难,由于有一个回调链一个接一个。直到错误到表现层呈现。

可读性会有一点牺牲。

还有一方面。 假设出现错误,我使用event bus 系统抛出错误的事件。可是这类解决方式类似 GOTO,在我看来,当你订阅多个事件但不能非常好的控制。你可能会懵掉。

Testing(測试)

关于測试。我依据不同的层选择了几个解决方式:

  • Presentation Layer(展示层): 使用android instrumentation 和 espresso 进行集成和功能測试。

  • Domain Layer(领域层): 使用JUnit 加 mockito 进行单元測试。

  • Data Layer(数据层): 使用Robolectric (这一层有android依赖) 加junit 加 mockito 进行集成和单元測试。

代码展示

我猜你在想代码在那里? 好吧,这就是我上面讲到内容的github连接

关于文件夹结构。提醒一下,不同的层使用模块来表示:

  • presentation: 是一个android模块代表展示层。
  • domain: 是一个没有android依赖的java模块。
  • data: 是一个android模块,全部数据的获取来源。
  • data-test: 数据层測试。因为使用Robolectric有一些限制问题,我不得不使用一个单独的模块。

结论

正如Bob大叔所说,“Architecture is About Intent, not Frameworks” 我全然统一这个说法。当然有很多不同的方式做这些事情(不同的实现方式),我非常确信每天你(像我)一样会面临非常多挑战,可是使用上面的方法。能够确保你的应用会:

  • 易维护.
  • 易測试.
  • 高内聚.
  • 低耦合.

最后我强力推荐你去实践一下,分享你的结果和经验。或许你会找到更好的方法:我们都知道持续改进 总是一个好的积极的事情。

我希望这篇文章对你有帮助,相同欢迎反馈不允许见。

Source code

  1. Clean architecture github repository – master branch
  2. Clean architecture github repository – releases

Further reading:

  1. Architecting Android..the evolution
  2. Tasting Dagger 2 on Android
  3. The Mayans Lost Guide to RxJava on Android
  4. It is about philosophy: Culture of a good programmer

Links and Resources

  1. The clean architecture by Uncle Bob
  2. Architecture is about Intent, not Frameworks
  3. Model View Presenter
  4. Repository Pattern by Martin Fowler
  5. Android Design Patterns Presentation

Architecting Android…The clean way?的更多相关文章

  1. 例子Architecting Android…The clean way?----代码分析

    Presention层:   整个应用启动的时候,就执行依赖的初始化.编译项目之后,Dagger依赖框架使用ApplicationComponent生成一个DaggerApplicationCOmpo ...

  2. 获取数据源数据的实现---Architecting Android

    UserRepository,这个接口,描述了Repository提供给用户的功能就是getUsers,getUser(ID).用户只管使用,其它细节无需理会. /** * Interface tha ...

  3. 一种更清晰的Android架构(转)

    一种更清晰的Android架构   一种更清晰的Android架构 原文链接 : Architecting Android…The clean way? 译者 : Mr.Simple & So ...

  4. 转:Android开发中的MVP架构(最后链接资源不错)

    Android开发中的MVP架构 最近越来越多的人开始谈论架构.我周围的同事和工程师也是如此.尽管我还不是特别深入理解MVP和DDD,但是我们的新项目还是决定通过MVP来构建. 这篇文章是我通过研究和 ...

  5. 转: Android开发中的MVP架构详解(附加链接比较不错)

    转: http://www.codeceo.com/article/android-mvp-artch.html 最近越来越多的人开始谈论架构.我周围的同事和工程师也是如此.尽管我还不是特别深入理解M ...

  6. Android开发MVP模式解析

    http://www.cnblogs.com/bravestarrhu/archive/2012/05/02/2479461.html 在开发Android应用时,相信很多同学遇到和我一样的情况,虽然 ...

  7. Android快速开发框架汇总

    知乎贴:Android 开发有什么好的架构么? 里面这篇不错:Architecting Android…The clean way? 知乎贴: 一.如果对App的性能.包size有要求,对代码有洁癖不 ...

  8. 设计模式笔记之二:Android开发中的MVP架构(转)

    写在前面,本博客来源于公众号文章:http://mp.weixin.qq.com/s?__biz=MzA3MDMyMjkzNg==&mid=402435540&idx=1&sn ...

  9. android MVP框架

    原文地址:http://blog.csdn.net/guxiao1201/article/details/40147209 在开发Android应用时,相信很多同学遇到和我一样的情况,虽然项目刚开始构 ...

随机推荐

  1. 啥叫sched-domain

    这周问过公司里专家,说cpu-load是说CPU的计算能力,但是从代码实在不知道cpu-load说的是啥! SD_SHARE_CPUPOWER 0X8000  domain的成员共享cpu power ...

  2. 【bzoj5015】[Snoi2017]礼物 矩阵乘法

    题目描述 热情好客的请森林中的朋友们吃饭,他的朋友被编号为 1-N,每个到来的朋友都会带给他一些礼物:.其中,第一个朋友会带给他 1 个,之后,每一个朋友到来以后,都会带给他之前所有人带来的礼物个数再 ...

  3. ORACLE 向BLOB字段中出入图片等二进制文件,使用Oracle SQl Developer工具

    使用PL/SQL也可以 create directory "image" as 'e:\'; --"image" 要带双引号,网上很多不带的,我测试时出错,并且 ...

  4. [codeforces] 527A Playing with Paper

    原题 简单的gcd #include<cstdio> #include<algorithm> typedef long long ll; using namespace std ...

  5. ZCC loves cube(cube)

    题目描述 调戏完了狗,ZCC开始玩起了积木.ZCC的面前有一块n*n的棋盘,他要用这些1*1*1的积木在棋盘上搭出一个宏伟的建筑.积木有三种颜色,ZCC认为一个建筑要被称为宏伟的应该满足能从正面看到的 ...

  6. 转 android Listview,gridview局部刷新,部分刷新 (仿QQ动态评论局部刷新)

    转自:http://blog.csdn.net/jdsjlzx/article/details/45582719 众所周知Listview和Gridview的刷新界面的方式是调用adapter.not ...

  7. Binary Indexted Tree 树状数组入门

    感谢http://www.cnblogs.com/xudong-bupt/p/3484080.html 树状数组(BIT)是能够完成下述操作的数据结构: 给定一初始值全为零的数列a1,a2a,a3.. ...

  8. Python-Python及PyCharm的下载与安装

    一.简介 Python:英 -[‘paɪθ ə n]或[‘paɪθɑn] 89年诞生 可用于软件开发: 游戏后台.搜索.图形界面 网站 C\S(Client/Server)软件 科学计算 亦可以进行系 ...

  9. 行为型设计模式之模板方法(Template Method)

    结构 意图 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.Te m p l a t e M e t h o d 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 适用性 一次性 ...

  10. [ CodeVS冲杯之路 ] P3038

    不充钱,你怎么AC? 题目:http://codevs.cn/problem/3038/ 按照题目给定的方法,一步步推下去,直到推到1就输出次数 至于-1的话,一开始想直接用数组判重,但是怕T掉,于是 ...