重构,夜未眠

已经读完了《App研发录》第一章,并且对整本书有了一个大致了解。我觉得有必要记录一下,对于架构方面,很多问题第一次我真的遇到过,但在不断的优化或者重构中,采用了书中相同的方式或者类似的方式解决了问题。比如我们App之前的收银流程,从金额计算到收银详情中间页面众多,要选优惠券或者核销优惠券,积分优惠等等。整个流程就要传十几个值到下单界面,并且有很多值中间是根据顾客选择方式进行变化的,第一次我使用了单个的intent方式传递,导致要定义很多常量接收,并且在接收的值上进行各种逻辑上的操作,所以最后代码逻辑不堪重负,所以第二次我决定重构。
今天我们来聊聊一个App最简单的架构是什么,或者换句话说应该注意哪些东西:

1.项目目录结构
2.关于重新定义Activity的生命周期
3.工具类的分类
4.基于AS的使用Gson数据生成结构体
5.网络请求数据的规范
6.界面中如何传递数据
7.列表万能模版
8.类型安全转换函数
9. App和html5交互
...

一.项目目录结构
至于说结构,我这里可能更多想说的是包的划分和功能模块的libs的提取。

包的划分来说有两种分法:

(1)所有的Activity放到一起, Adapter放到一起 ,工具类放到一起 ,自定义控件放到一起 ,等等。

(2)按模块划分,例如我首页是门店,门店下面包含会员池,发会员卡,发优惠券,收银等等那么将这里所有的功能放到一个Home包下,然后再在这个包下面进行细致划分(Activity,Adapter等等)。

其实我个人看这两种方法各有所长,可根据自己项目大小进行划分,小中型项目建议第一种,超大型项目建议第二种。

功能模块libs提取:
都知道,对于我们的项目,我们会定义一个libs,然后主体项目去依赖它,但是这个libs又应该放些什么呢?又应该注意哪些呢?

(1)BaseActivity  的定义
(2)图表库
(3)支付相关封装
(4)推送或者js交互封装
(5)第三方分享类库

当然以上三四点只是我项目里面的一个大致封装,可采用类似主体项目包的划分,只不过提供主体项目共有的服务,让主体项目的逻辑等更加简单,像libs库我建议像分享,第三方推送,第三方聊天等等做出单独的libs,进行单独依赖。

二.关于重新定义Activity的生命周期
Activity具体声明周期我不在这里进行详细描述,至于重新定义,主要进行细化了Activity的onCreate()方法的操作。有时候会在 onCreate()方法里面写成百上千行的代码。但是我们有没有回过头来想想我们具体的在onCreate()方法里面做了哪些事情,无法set一个布局,获取控件,初始化数据,网络请求加逻辑,所以在BaseActivity重写onCreate()方法,并且在onCreate()方法中添加四个abstract方法,在子类必须去实现这四个方法。

1.setView(); // 初始化布局
2.initView(); // 初始化控件
3.initData(); // 数据初始化
4.formatContent(); // 具体逻辑处理

这是我在BaseActivity中定义的几个抽象方法,当然可以增加更多方法,也不一定是抽象方法,否则子类就必须都去实现这些方法了。

三.工具类的分类
至于工具类的分类,我的建议是每个相似的工具方法定义到一个类中,比如颜色处理类,图片处理类,json处理类,SharedPreferences工具类等等。所有的同类都定义个工具类,进行分开处理各自的分工,刚到公司时候,只在工具包下发现了一个utils类,里面各种工具方法,在使用和维护上面是个有很多的麻烦和隐患。

四.基于AS的使用Gson数据生成结构体
现在客户端和服务端通信大多使用的是Gson数据的传递,我们解析数据时候也大多会通过Gson包生成相应的实体,那么我们就需要构建实体类,而构建实体类是有快速构建方法的,只需要安装一个插件即可。方法:http://www.jianshu.com/p/b83ea5e32ee1

五.网络请求数据的规范
现在有很多的网络请求框架,大致原理都很相似,如果我们自己去写一个网络请求框架,那么在一个Activity中需要哪些构建呢?我觉得三行代码即可(不包括数据请求之后的操作),(1)发起网络请求 (2)成功的回调(3)失败的回调
例如登陆的操作:

1.HttpRequestAsyncTask.requestLogin(this, USER_LOGIN_INDEX, user_name, user_password);
2.@Override public void requestJsonObject(String result, int index) { }
3.@Override public void Error(String error, int index) { }

注意上面的index作用,因为我们一个页面中往往有多个网络的请求,必须进行网络请求的区分。

六.界面中如何传递数据
说起数据传输我们会考虑使用Bundle传递或者直接使用Intent,但有一下情景:第一个界面计算需要收银100元,第二个界面有优惠券的兑换和使用,兑换了一张折扣券,可能还需要收银70元,然后前面几次购买累计的有积分,积分折扣之后,到下单详情界面,然后确认下单。可以知道这个直接你的收银金额在传递的过程中在不断的修改,并且到下一个面时候又需要封装,所以后来我想了一个办法那就是传递时候定义个实体对象,只往里面增加属性,然后序列化传递,到下个页面直接修改对象中的值,然后再继续传递,所以会少很多的逻辑操作。

七.列表万能模版
我们现在常用的Adapter会大致会有listview的Adapter和RecyclerView的Adapter,无论何种。我们都需要考虑这样几个问题:

1.Adapter的优化
2.支持添加头部布局和脚布局(下拉刷新,上拉加载更多)
3.简化分页逻辑(不用判断是否拉到底部等等逻辑)
4.减少Adapter中逻辑操作等不同情况(列表中不同的item)
5.缺省页,网络错误页
6.多种刷新数据方式的封装(RecyclerView全局刷新,局部刷新)

八.类型安全转换函数
App中有很多情况都是因为数据转换异常,例如(NumberFormatException)。这样的情况我相信很多,并且从服务端传过来的数据对于我们来说往往是不可控的。我们平时会采用try catch的方法来进行异常处理,但是有太多地方了。所以我建议我们在自己的框架中有个这样的方法,当我们将一个字段toString()时候或者强转时候,先判断是否为null,是否可以强转,不可以的话直接给个默认值。

九. App和html5交互
随着h5的快速发展,在我们的app中很多时候会插入h5界面,例如h5界面的商城,在支付时候需要调用本地支付宝或者微信支付,那么这个就牵扯到一个js的交互,在这里推荐一个比较好用的js交互框架:JsBridge:https://github.com/lzyzsd/JsBridge

以上我觉得是一个App框架中应该注意的一些地方吧,对于列表万能模版(RecyclerView)和App和html5交互后面分两次博客来说。

明天周五啦!!!!

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 124,771评论 16 535
  • 1.1,重新规划Android项目结构 Activity:存放与业务无关的Activity基类 BaseActiv...
    lookid阅读 24评论 0 0
  • 1.1重新规划Android项目结构 基本上项目目录尽可能细分,容易快速查找界面。现在感觉mvp模式不错,可以采用...
    聪聪的豆芽阅读 22评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 70,835评论 12 116
  • ​好物清单‖无限回购好物推荐 很早就想写这个主题了,从18岁开始护肤当小白鼠,走过了很长一段弯路,买DIY的化妆水...
    Vin姐阅读 780评论 0 9