淘先锋技术网

首页 1 2 3 4 5 6 7

Android Clean Architecture系列之一——清洁的Android架构
原文链接点我

开始

我们都知道,编写高质量代码非常困难而且复杂。不仅仅要满足需求,还要考虑强壮性、可维护性、可测试性以及足够的灵活性以便应对后续的版本迭代。这就是为什么清洁架构是一种开发软件的优秀方式。
这个理念其实很简单:清洁架构包含一系列最佳实践来让软件具备以下特性:
- 框架独立性
- 容易测试
- UI独立性
- 数据独立性
- 其他任何外部功能的独立性mage description here](http://fernandocejas.com/wp-content/uploads/2014/09/clean_architecture1.png)
并非一定像上图一样包含四个层次,上图只是一个简图。但是关于依赖规则却是需要仔细考虑的问题:代码只能由外层向内层依赖,内层的任何部分都对外层的具体实现一无所知。

以下是一些与这一设计方式相关的名词:
- 实体(Entities):应用程序中的业务对象
- 用例(Use Cases):用例用来组织管理流入和流出实体的数据流,用例也被称为交互(Interactors)。
- 界面适配器(Interface Adapters):适配器将实体和用例转换为便于使用的数据形式。展现器(Presenters)和控制器(Controllers)都包含在此处。
- 框架和驱动:这是所有细节所在,包括UI、工具、框架等等。

查看更为详细的说明,请参考此此文
和该视频

我们的方案

有这样一个小例子:从服务器获取一个好友和用户的列表,当点击列表中的任何一人时,跳转到一个显示该人详情的新页面。

Android架构

主要目标是关联性的分离,即保持业务逻辑对其他部分一无所知,这样就可以不依赖任何外部模块来进行测试。
要实现这点。我的建议是将整个项目拆分为三层,每一层都有各自的作用并且与其他各层保持隔离。
需要提及的是,每一层都是用各自的数据模型,不能在整个应用内使用数据模型,这需要额外的代价。
以下是此种架构的图解:
enter image description here
注意:这里我并没有使用第三方库(除了使用Gson进行解析,以及使用一些测试框架),因为我希望示例工程能看起来更加清洁。在实际项目中,使用ORM来处理数据存储,是用注解工具或者其他工具来简化编程都是很好的做法,不要重复造轮子。

展现器(Presenter)层

与视图和动画相关的逻辑位于此层,他仅仅是使用了MVP模式,当然也可以使用MVC或MVVM。这里不想过多涉及几种模式的讨论,但是在这里Fragment和Activity都只是视图,他们内部只包含UI相关的逻辑。该层中的Presenter通过Interactor暴露接口给外界,这些操作在UI线程以外的线程中完成,然后使用回调传递数据并进行视图展现。
enter image description here
这里是一个关于MVP和MVVM的很好的例子,来自Pedro GómezEffective Android UI

业务逻辑层

业务逻辑都位于该层,对于Android工程,所有Interactor的具体实现都在这里。该层是纯粹的Java模型,不含有任何Android依赖,所有外部模块都通过接口来与业务逻辑对象对接。

数据层

所有应用程序所需数据位于该层,通过用户数据存储接口(接口位于业务逻辑层)的实现来使用数据存储中的数据。访问数据存储时通过一个工厂,采用不同策略来访问来自不同数据源的数据。例如,当通过id查询用户的时候,如果缓存中已有该用户,就会使用缓存中的数据,否则就联网查询数据最后存储到缓存中。
这一切背后的理念在于:对客户端来说,数据来源是透明的,数据来自于内存或硬盘或网络等都不重要,结果都是数据将会被获取到。enter image description here

错误处理

我们的策略是使用回调,例如,回调可能包含两个方法:onResponse()onError()。后者将一场封装到一个叫ErrorBundle的类中:这种处理方式会带来一些问题,因为错误不断向外层传递直到被UI层展示处理需要经历多个回调方法,代码的可读性可能因此下降。
另一种方式是,使用类似EventBus的方式,当发成错误时抛出一个事件。但是这种处理方式有点类似GOTO语句,也并不是一种好的方式。

测试

对不同层,我选择了一下一些测试方案:
- 展现器层:使用Android工具和espresso进行整体测试和功能测试
- 业务逻辑层:使用JUnit和mockito进行单元测试和用例测试
- 使用Robolectric、JUnit和mockito进行整体测试和单元测试

给我来点代码吧

代码在此,需要指出的是,不同层次是使用不同模块来组织的:
- presentation模块:展现器层
- domain模块:只有Java模型,没有Android依赖
- data模块:所有数据来自该模块
- data-test模块:data层的测试模块。

结论

像鲍勃叔叔说的架构取决于目的,而不是框架,我非常赞同这点。使用以上结构,可以保证应用程序具备以下特点:
- 易于维护
- 易于测试
- 内聚性强
- 耦合性低
非常推荐可以自己按以上结构尝试架构应用,并且在实践中不断改进架构,非常希望以上文章对你有用。