你的位置:首页 > 软件开发 > 操作系统 > Android 项目重构之路:实现篇

Android 项目重构之路:实现篇

发布时间:2015-11-19 19:00:15
前两篇文章《Android项目重构之路:架构篇》和《Android项目重构之路:界面篇》已经讲了我的项目开始搭建时的架构设计和界面设计,这篇就讲讲具体怎么实现的,以实现最小化可用产品(MVP)的目标,用最简单的方式来搭建架构和实现代码。IDE采用Android Studio,De ...

前两篇文章《Android项目重构之路:架构篇》和《Android项目重构之路:界面篇》已经讲了我的项目开始搭建时的架构设计和界面设计,这篇就讲讲具体怎么实现的,以实现最小化可用产品(MVP)的目标,用最简单的方式来搭建架构和实现代码。

IDE采用Android Studio,Demo实现的功能为用户注册、登录和展示一个券列表,数据采用我们现有项目的测试数据,接口也是我们项目中的测试接口。

项目搭建

根据架构篇所讲的,将项目分为了四个层级:模型层、接口层、核心层、界面层。四个层级之间的关系如下图所示:

Android 项目重构之路:实现篇

实现上,在Android Studio分为了相应的四个模块(Module):model、api、core、app。apply plugin: 'com.android.application'apply plugin: 'com.android.library'

  • 建立模块之间的依赖关系。有两种方法可以设置:dependencies {

    通过上面两种方式的任意一种,创建了模块之间的依赖关系之后,每个模块的build.gradle的dependencies项的结果将会如下:dependencies {

    api:

     dependencies {

    core:

     dependencies {

    app:

     dependencies {

     

  • 创建业务对象模型

    业务对象模型统一存放于model模块,是对业务数据的封装,大部分都是从接口传过来的对象,因此,其属性也与接口传回的对象属性相一致。在这个Demo里,只有一个业务对象模型,封装了券的基本信息,以下是该实体类的代码:

     /**

     

    接口层的封装

    在这个Demo里,提供了4个接口:一个发送验证码的接口、一个注册接口、一个登录接口、一个获取券列表的接口。这4个接口具体如下:

    • 发送验证码接口{ "event": "0", "msg": "success" }

       

    • 注册接口{ "event": "0", "msg": "success" }

       

    • 登录接口{ "event": "0", "msg": "success" }

       

    • 券列表{ "event": "0", "msg": "success", "maxCount": 125, "maxPage": 7, "currentPage": 1, "pageSize": 20, "objList":[

       

    在架构篇已经讲过,接口返回的json数据有三种固定结构:

     {"event": "0", "msg": "success"}

    因此可以封装成实体类,代码如下:

     public class ApiResponseT> {

    上面4个接口,URL和appKey都是一样的,用来区别不同接口的则是method字段,因此,URL和appKey可以统一定义,method则根据不同接口定义不同常量。而除去appKey和method,剩下的参数才是每个接口需要定义的参数。因此,对上面4个接口的定义如下:

     public interface Api {

    Api的实现类则是ApiImpl了,实现类需要封装好请求数据并向服务器发起请求,并将响应结果的数据转为ApiResonse返回。而向服务器发送请求并将响应结果返回的处理则封装到http引擎类去处理。另外,这里引用了gson将json转为对象。ApiImpl的实现代码如下:

     public class ApiImpl implements Api {

    而http引擎类的实现如下:

     public class HttpEngine {

    至此,接口层的封装就完成了。接下来再往上看看核心层吧。

    核心层的逻辑

    核心层处于接口层和界面层之间,向下调用Api,向上提供Action,它的核心任务就是处理复杂的业务逻辑。先看看我对Action的定义:

     public interface AppAction {

    首先,和Api接口对比就会发现,参数并不一致。登录并没有iemi和loginOS的参数,获取券列表的参数里也少了pageSize。这是因为,这几个参数,跟界面其实并没有直接关系。Action只要定义好跟界面相关的就可以了,其他需要的参数,在具体实现时再去获取。public interface ActionCallbackListenerT> {

    接下来再看看Action的实现。首先,要获取imei,那就需要传入一个Context;另外,还需要loginOS和pageSize,这定义为常量就可以了;还有,要调用接口层,所以还需要Api实例。而接口的实现分为两步,第一步做参数检查,第二步用异步任务调用Api。具体实现如下:

     public class AppActionImpl implements AppAction {

    简单的实现代码就是这样,其实,这还有很多地方可以优化,比如,将参数为空的检查、手机号有效性的检查、数字型范围的检查等等,都可以抽成独立的方法,从而减少重复代码的编写。异步任务里的代码也一样,都是可以通过重构优化的。另外,需要扩展时,比如添加缓存,那就在调用Api之前处理。public class KApplication extends Application {

    另外,一个Activity的基类也是很有必要的,可以减少很多重复的工作。基类的代码如下:

     public abstract class KBaseActivity extends FragmentActivity {

    再看看登录的Activity:

     public class LoginActivity extends KBaseActivity {

    登录页的布局文件则如下:

     LinearLayout :android="http://schemas.android.com/apk/res/android"

    可以看到,EditText的id命名统一以edit开头,而在Activity里的控件变量名则以Edit结尾。按钮的onClick也统一用toXXX的方式命名,明确表明这是一个将要做的动作。还有,string,dimen也都统一在相应的资源文件里按照相应的规范去定义。public abstract class KBaseAdapterT> extends BaseAdapter {

    这个抽象基类集成了设置数据的方法,每个具体的适配器类只要再实现各自的getView方法就可以了。本Demo的券列表的适配器如下:

     apply plugin: 'com.android.application'apply plugin: 'com.android.library'
  • 建立模块之间的依赖关系。有两种方法可以设置:dependencies {

    通过上面两种方式的任意一种,创建了模块之间的依赖关系之后,每个模块的build.gradle的dependencies项的结果将会如下:dependencies {

    api:

     dependencies {

    core:

     dependencies {

    app:

     dependencies {

     

  • 创建业务对象模型

    业务对象模型统一存放于model模块,是对业务数据的封装,大部分都是从接口传过来的对象,因此,其属性也与接口传回的对象属性相一致。在这个Demo里,只有一个业务对象模型,封装了券的基本信息,以下是该实体类的代码:

     /**

     

    接口层的封装

    在这个Demo里,提供了4个接口:一个发送验证码的接口、一个注册接口、一个登录接口、一个获取券列表的接口。这4个接口具体如下:

    • 发送验证码接口{ "event": "0", "msg": "success" }

       

    • 注册接口{ "event": "0", "msg": "success" }

       

    • 登录接口{ "event": "0", "msg": "success" }

       

    • 券列表{ "event": "0", "msg": "success", "maxCount": 125, "maxPage": 7, "currentPage": 1, "pageSize": 20, "objList":[

       

    在架构篇已经讲过,接口返回的json数据有三种固定结构:

     {"event": "0", "msg": "success"}

    因此可以封装成实体类,代码如下:

     public class ApiResponseT> {

    上面4个接口,URL和appKey都是一样的,用来区别不同接口的则是method字段,因此,URL和appKey可以统一定义,method则根据不同接口定义不同常量。而除去appKey和method,剩下的参数才是每个接口需要定义的参数。因此,对上面4个接口的定义如下:

     public interface Api {

    Api的实现类则是ApiImpl了,实现类需要封装好请求数据并向服务器发起请求,并将响应结果的数据转为ApiResonse返回。而向服务器发送请求并将响应结果返回的处理则封装到http引擎类去处理。另外,这里引用了gson将json转为对象。ApiImpl的实现代码如下:

     public class ApiImpl implements Api {

    而http引擎类的实现如下:

     public class HttpEngine {

    至此,接口层的封装就完成了。接下来再往上看看核心层吧。

    核心层的逻辑

    核心层处于接口层和界面层之间,向下调用Api,向上提供Action,它的核心任务就是处理复杂的业务逻辑。先看看我对Action的定义:

     public interface AppAction {

    首先,和Api接口对比就会发现,参数并不一致。登录并没有iemi和loginOS的参数,获取券列表的参数里也少了pageSize。这是因为,这几个参数,跟界面其实并没有直接关系。Action只要定义好跟界面相关的就可以了,其他需要的参数,在具体实现时再去获取。public interface ActionCallbackListenerT> {

    接下来再看看Action的实现。首先,要获取imei,那就需要传入一个Context;另外,还需要loginOS和pageSize,这定义为常量就可以了;还有,要调用接口层,所以还需要Api实例。而接口的实现分为两步,第一步做参数检查,第二步用异步任务调用Api。具体实现如下:

     public class AppActionImpl implements AppAction {

    简单的实现代码就是这样,其实,这还有很多地方可以优化,比如,将参数为空的检查、手机号有效性的检查、数字型范围的检查等等,都可以抽成独立的方法,从而减少重复代码的编写。异步任务里的代码也一样,都是可以通过重构优化的。另外,需要扩展时,比如添加缓存,那就在调用Api之前处理。public class KApplication extends Application {

    另外,一个Activity的基类也是很有必要的,可以减少很多重复的工作。基类的代码如下:

     public abstract class KBaseActivity extends FragmentActivity {

    再看看登录的Activity:

     public class LoginActivity extends KBaseActivity {

    登录页的布局文件则如下:

     LinearLayout :android="http://schemas.android.com/apk/res/android"

    可以看到,EditText的id命名统一以edit开头,而在Activity里的控件变量名则以Edit结尾。按钮的onClick也统一用toXXX的方式命名,明确表明这是一个将要做的动作。还有,string,dimen也都统一在相应的资源文件里按照相应的规范去定义。public abstract class KBaseAdapterT> extends BaseAdapter {

    这个抽象基类集成了设置数据的方法,每个具体的适配器类只要再实现各自的getView方法就可以了。本Demo的券列表的适配器如下:

     public class CouponListAdapter extends KBaseAdapterCouponBO> {

    而券列表的Activity简单实现如下:

     public class CouponListActivity extends KBaseActivity implements SwipeRefreshLayout.OnRefreshListener {

     

    完结

    终于写完了,代码也终于放上了github,为了让人更容易理解,因此很多都比较简单,没有再进行扩展。

    1public class CouponListAdapter extends KBaseAdapterCouponBO> {

    而券列表的Activity简单实现如下:

     public class CouponListActivity extends KBaseActivity implements SwipeRefreshLayout.OnRefreshListener {

     

    完结

    终于写完了,代码也终于放上了github,为了让人更容易理解,因此很多都比较简单,没有再进行扩展。

    全能程序员交流QQ群290551701,聚集很多互联网精英,技术总监,架构师,项目经理!开源技术研究,欢迎业内人士,大牛及新手有志于从事IT行业人员进入!


     

    海外公司注册、海外银行开户、跨境平台代入驻、VAT、EPR等知识和在线办理:https://www.xlkjsw.com

    原标题:Android 项目重构之路:实现篇

    关键词:Android

    *特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

    可能感兴趣文章

    我的浏览记录