项目分为了四个层级:模型层、接口层、核心层、界面层。模型层定义了所有的模型;接口层封装了服务器提供的API;核心层处理所有业务逻辑;界面层就处理界面的展示。几个层级之间的关系如下图所示:

层级关系:模型层,用于各层的数据交互;接口层为核心层提供实现API;核心层用于提供处理业务逻辑;界面层用于和界面交互。

下面展开说明具体的每个层次:

接口层

接口层封装了网络底层的API,并提供给核心层调用。刚开始,为了简单,该层的核心类我只定义了4个:

  1. PostEngine,请求引擎类,对请求的发送和响应结果进行处理;
  2. Response,响应类,封装了Http请求返回的数据结构;
  3. Api,接口类,定义了所有接口方法;
  4. ApiImpl,接口实现类,实现所有接口方法。

PostEngine将请求封装好发送到服务器,并对响应结果的json数据转化为Response对象返回。Response其实就是响应结果的json数据实体类,json数据是有固定结构的,分为三类,如下:

{"event": "0", "msg": "success"}
{"event": "0", "msg": "success", "obj":{...}}
{"event": "0", "msg": "success", "objList":[{...}, {...}], "currentPage": 1, "pageSize": 20, "maxCount": 2, "maxPage": 1}

event为返回码,0表示成功,msg则是返回的信息,obj是返回的单个数据对象,objList是返回的数据对象数组,currentPage表示当前页,pageSize则表示当前页最多对象数量,maxCount表示对象数据总量,maxPage表示总共有多少页。根据此结构,Response基本的定义如下:

public class Response<T> {
private String event;
private String msg;
private T obj;
private T objList;
private int currentPage;
private int pageSize;
private int maxCount;
private int maxPage; //getter和setter方法
...
}

每个属性名称都要与json数据对应的名称相一致,否则无法转化。obj和objList用泛型则可以转化为相应的具体对象了。

Api接口类定义了所有的接口方法,方法定义类似如下:

public Response<Void> login(String loginName, String password);
public Response<VersionInfo> getLastVersion();
public Response<List<Coupon>> listNewCoupon(int currentPage, int pageSize);

ApiImpl则实现所有Api接口了,实现代码类似如下:

@Override
public Response<Void> login(String loginName, String password) {
try {
String method = Api.LOGIN;
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("loginName", loginName));
params.add(new BasicNameValuePair("password", EncryptUtil.makeMD5(password)));
TypeToken<Response<Void>> typeToken = new TypeToken<Response<Void>>(){};
return postEngine.specialHandle(method, params, typeToken);
} catch (Exception e) {
//异常处理
}
}

实现中将请求参数和返回的类型定义好,调用PostEngine对象进行处理。
接口层的核心基本上就是这些了。

核心层

核心层介于接口层和界面层之间,主要处理业务逻辑,集中做数据处理。向上,给界面层提供数据处理的接口,称为Action;向下,调用接口层向服务器请求数据。向上的Action中定义的方法类似如下:

public void getCustomer(String loginName, CallbackListener<Customer> callbackListener);

这是一个获取用户信息的方法,因为需要向接口层请求服务器Api数据,所以添加了callback监听器,在callback里对返回的数据结果进行操作。CallbackListener就定义了一个成功和一个失败的方法,代码如下:

public interface CallbackListener<T> {
/**
* 请求的响应结果为成功时调用
* @param data 返回的数据
*/
public void onSuccess(T data); /**
* 请求的响应结果为失败时调用
* @param errorEvent 错误码
* @param message 错误信息
*/
public void onFailure(String errorEvent, String message);
}

接口的实现基本分为两步:

  1. 参数检查,检查参数的合法性,包括非空检查、边界检查、有效性检查等;
  2. 使用异步任务调用接口层的Api,返回响应结果。

需要注意的是,Action是面向界面的,界面上的数据可能需要根据不同情况调用不同的Api。
后续扩展可以在这里添加缓存,但也要视不同情况而定,比如有些变化太快的数据,添加缓存就不太适合了。

界面层

界面层处于最上层,其核心就是负责界面的展示。因为公司有为不同商户定制不同app的需求,因此,这里就需要建立多个app的界面,这是一个很麻烦的事情,还好,Android Studio提供了很方便的方法可以大大减少工作量,主要通过设置Gradle,不同app可以添加不同的productFlavors。

界面层package的定义我也并不按照旧版的功能模块划分,而根据不同类型划分,主要分为以下几个包:

其中,activity、adapter、fragment各自都有一个基类,做统一的处理,比如定义了一些共用的常量、对象和方法等。
界面层是最复杂,最容易变得混乱不堪,最容易出问题的层级。所以,从架构到代码,很多东西都需要设计好,以及规范好,才能保证程序易维护、易扩展。后续的文章里将会详细分享下我在这方面的经验。

模型层

模型层横跨所有层级,封装了所有数据实体类,基本上也是跟json的obj数据一致的,在接口层会将obj转化为相应的实体类,再通过Action传到界面层。另外,模型层还定义了一些常量,比如用户状态、支付状态等。在Api里返回的是用1、2、3这样定义的,而我则用枚举类定义了这些状态。用枚举类定义,就可以避免了边界的检查,同时也更明了,谁会记得那么多1、2、3都代表什么状态呢。然而用枚举类定义的话,就必须能将1、2、3转化为相应的枚举常量。这里,我提供两种实现方式:
1.使用gson的@SerializedName标签,比如0为FALSE,1为TRUE,则可以如下定义:

public enum BooleanType {
@SerializedName("0")
FALSE,
@SerializedName("1")
TRUE
}

2.通过定义一个value,如下:

public enum BooleanType {
FALSE("0"),
TRUE("1"); private String value; BooleanType(String value) {
this.value = value;
} public String getValue() {
return value;
}
}

通过gson的方式,直接访问TRUE或FALSE就会自动序列化为1或0;如果通过第二种方式,因为没有序列化,则需要通过getValue方式获取1或0。

原文:http://keeganlee.me/post/android/20150605

Android 架构 1.架构的更多相关文章

  1. [转]Android App整体架构设计的思考

    1. 架构设计的目的 对程序进行架构设计的原因,归根到底是为了提高生产力.通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点, ...

  2. Android入门(二):Android的系统架构

    android的系统架构和其操作系统一样,采用了分层的架构.从架构图看,android分为四个层,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和linux核心层.   从技术方面看,An ...

  3. Android系统的架构

    android的系统架构和其操作系统一样,采用了分层的架构.从架构图看,android分为四个层,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和linux核心层. 1.应用程序 Andr ...

  4. fir.im Weekly - iOS/Android 应用程序架构解析

    假如问你一个iOS or Android app的架构,你会从哪些方面来说呢? 本期 fir.im Weekly 收集了关于  iOS/Android 开发资源,也加入了一些关于 Web 前端方面的分 ...

  5. Android 控件架构及View、ViewGroup的测量

    附录:示例代码地址 控件在Android开发的过程中是必不可少的,无论是我们在使用系统控件还是自定义的控件.下面我们将讲解一下Android的控件架构,以及如何实现自定义控件. 1.Android控件 ...

  6. Android 的系统架构

    Android 的系统架构 Android其本质就是在标准的Linux系统上增加了Java虚拟机Dalvik,并在Dalvik虚拟机上搭建了一个JAVA的application framework,所 ...

  7. Android App的架构设计:从VM、MVC、MVP到MVVM

    随着Android应用开发规模的扩大,客户端业务逻辑也越来越复杂,已然不是简单的数据展示了.如同后端开发遇到瓶颈时采用的组件拆分思想,客户端也需要进行架构设计,拆分视图和数据,解除模块之间的耦合,提高 ...

  8. Android系统四层架构分享

    Android系统四层架构 个人网站:http://www.51pansou.com Android视频下载:Android视频 Android源码下载:Android源码 如果把Android系统看 ...

  9. Android的系统架构

    转自Android的系统架构 从上图中可以看出,Android系统架构为四层结构,从上层到下层分别是应用程序层.应用程序框架层.系统运行库层以及Linux内核层,分别介绍如下:     1)应用程序层 ...

  10. 实时Android语音对讲系统架构

    本文属于Android局域网内的语音对讲项目系列,<通过UDP广播实现Android局域网Peer Discovering>实现了局域网内的广播及多播通信,本文将重点说明系统架构,音频信号 ...

随机推荐

  1. 前端部署: nginx配置

    前提:nginx 已安装 简介:nginx(engine x) 是一个高性能的HTTP和反向代理服务,也是一个IMAP/POP3/SMTP服务.Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Ram ...

  2. Linux动态库生成以及调用

    Linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件. 在链接动态库生成可执行文件时,并不会把动态库的代码复制到执行文件中,而是 ...

  3. hadoop之shuffle详解

    Shuffle描述着数据从map task输出到reduce task输入的这段过程. 如map 端的细节图,Shuffle在reduce端的过程也能用图上标明的三点来概括.当前reduce copy ...

  4. 【SPOJ - QTREE2】树链剖分

    http://acm.hust.edu.cn/vjudge/problem/19960 题意: 有一棵N个节点的树(1<=N<=10000),N-1条边,边的编号为1~N-1,每条边有一个 ...

  5. bzoj3918 [Baltic2014]Postman

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3918 [题解] 每日至少更一题啊qwq凑任务(迷 明显猜个结论:随便搜环就行了 然后搜环姿势 ...

  6. [BZOJ1024][SCOI2009]生日快乐解题报告

    Description windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕.现在包括windy,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋 ...

  7. CVE-2016-6662 mysql RCE测试

    参考:http://bobao.360.cn/learning/detail/3027.html ,我尝试第一种方法 1.先修改mysql_hookandroot_lib.c里面的反弹地址和端口: # ...

  8. Linux 开机自动挂载windows分区

    blkid 查看 uuid如下ps:或者使用uuidgen <设备>查看具体设备的uuidreddusty@reddusty-X550JK:~$ sudo blkid[sudo] pass ...

  9. python基础代码(猜年龄、从最内层跳出多层循环、简单的购物车程序)

    1.猜年龄 , 可以让用户最多猜三次! age = 55 i=0 while i<3: user_guess = int (input ("input your guess:" ...

  10. 入园的第一篇--where、where

    这篇是入园的第一篇随便,后面我会将自己几年前写的博文都转到这里.哎,其实说到博文的事情,我就很郁闷,甚至有些恼火,后面我会详细说说这中间的过程,也许能帮助某些人避免遇到类似的事情.突然想起<西游 ...