在前一篇文章《Android项目重构之路:架构篇》中已经简单说明了项目的架构,将项目分为了四个层级:模型层、接口层、核心层、界面层。其中,最上层的界面,是变化最频繁的一个层面,也是最复杂最容易出问题的一个层面,若是规划很差,很容易作着作着,又乱成一团了。
要规划好界面层,至少应该遵循几条基本的原则:android
保持规范性:定义好开发规范,包括书写规范、命名规范、注释规范等,并按照规范严格执行;数组
保持单一性:布局就只作布局,内容就只作内容,各自分离好;每一个方法、每一个类,也只作一件事情;缓存
保持简洁性:保持代码和结构的简洁,每一个方法,每一个类,每一个包,每一个文件,都不要塞太多代码或资源,感受多了就应该拆分。网络
规范性
每一个人的编码习惯和风格都不一样,不说那些缺少良好编码习惯的开发人员,就连那些已经养成良好编码习惯的人员,不少方面都会不一样。好比缩进,有的喜欢4个空格,有的喜欢两个空格;好比变量名,有的喜欢m开头,例如mValue,有的喜欢直接就命名为value。若是不设定好规范,让每一个人都按照本身的习惯和风格去编码,久了确定乱,尤为当团队中存在还没养成良好编码习惯的人员时,更容易乱。所谓无规矩不成方圆,若无规范,久必乱。定义好规范,才能统一风格,才可提升代码可读性,同时也提升了维护性,还减低了引入bug的机会。
开发规范并无统一的标准,在这里,我只是根据本身的经验对一些点提供一点建议,仅供参考。架构
不少人都习惯用Tab缩进,不论是规范4个空格仍是2个空格,统一设置好Tab缩进的size就行了,这样就不用让每一个人都去敲空格。工具
一个好的命名,一眼就能够从名字中看到它是干吗的,作什么用,什么类型等等。举个id命名的例子,看到有些团队喜欢将一些控件缩写,好比TextView缩写为tv,ListView缩写为lv,这种缩写却是挺简洁的,可是并不能一眼就能看出它是什么,对于不熟悉的人来讲,谁知道tv和lv是什么啊,还不如用text和list更明确些。我喜欢的id命名结构为:控件_范围_功能,例如:edit_login_password,这是一个登陆页的密码输入框。布局
文字大小的单位应该统一用sp,其余元素用dp。由于这两个单位是与设备分辨率无关的,可以解决在不一样分辨率设备上显示效果不一样的问题。另外,SDK里面,对文字大小系统默认是用sp单位的,但其余元素单位默认却不是dp,而是px的,同时也没有提供dp的设置接口,因此,本身写两个dp和px转换的方法是颇有必要的。post
最重要的并不在于规范怎么定义,而是在于规范的严格执行。若是规范定义好了,但却不遵照,那规范就等于形同虚设,所以,规范一旦设定,就要严格执行。编码
单一性
咱们都知道,面向对象设计中,有一个基本原则就是单一职责原则,它规定一个类应该只有一个发生变化的缘由。而这里说的单一性,不仅是规定类,也规定了方法、包,甚至到最大层面的分层架构。保持单一性是减低耦合度的关键标准,其目的就是各方面的解耦。架构上的分层就是最大层面的解耦,而方法上的单一就是最小层面的解耦了。spa
界面上的单一,首先是界面的布局和界面的数据应该分离。这一点,Android已经用layout和Activity作好解耦了,咱们只要确保用layout文件排好布局,在Activity展现数据就行了。另外,界面数据的获取和展现也应该分离。不少开发团队习惯将数据的获取和展现都放在Activity或Fragment里完成的,架构篇的读者里也有人反映了这个状况,请求接口、获取数据、检查数据、显示数据更新UI,全都在界面上完成的。这样子的话,当数据的获取发生改变时,好比要添加缓存,这时候界面就须要改动了,当数据的展现也须要修改时,好比某个控件要展现其余数据,界面也同样须要改动,也就是说,界面上已经有两个发生变化的缘由,这就违反了单一职责原则。
界面上的单一,就是要保持界面上每一个维度都作好分离,从界面的布局,到数据的获取,数据的检查,数据的展现。
定义包以前,须要先想好它的职责是什么,明肯定义并确保它只有一个职责。例如,com.keegan.activity,就是activity类的包,不会有其余组件;com.keegan.adapter,就是存放各类适配器的包;com.keegan.util就是工具包了。一样,类的定义,也是须要明确它的单一职责。有些人习惯将adapter写在Activity里,由于以为这个adapter只在这个Activity里用到,不必再把它独立出来。之前的我也是这么干的,这么作了一段时间以后,以为实在糟糕透了,重复的代码没法复用,界面上的一点小需求调整时,不少代码须要跟着调整。后来,进行了一番重构,将全部adapter独立了出来,并抽象出了一个adapter的基类,自此,当须要再添加adapter时,编写的代码量大大减小了,当界面需求调整时,修改的地方也大大减小了。因此,不要让一个类作太多事情,要分离好各类元素,每一个元素只作一件简单的事。
方法的单一,表现为一个方法是对一个行为的封装。然而,一个行为又能够拆分为多个步骤,每一个步骤其实也是一个更细的行为,又能够封装成一个新的方法。所以,方法嵌套方法是一种常态。那么,保持方法的单一性,关键并不在于怎么定义这个方法的行为,而在于这个行为要怎么拆分红更细的行为。举个例子,一般在Activity的onCreate方法,作数据的初始化,细分出来就分为了:控件的初始化、逻辑变量的初始化、数据的加载和展现。数据的加载和展现能够再细分:从缓存加载数据、从网络加载数据、展现数据。每一个细化的行为都应该封装为一个独立的方法,这样,才真正符合方法的单一性。
Android提供了各类资源文件,strings.xml用来存储字符串,arrays.xml用来存储字符串数组,colors.xml用来存储颜色值,dimens.xml用来存储尺寸值,等等。资源文件的单一,是说全部相关的资源信息要在资源文件里定义并引用到代码或布局文件里,而不是在代码或布局文件里直接定义。不少开发人员,为了图方便,应用界面中出现的字符串常常在代码或布局文件里直接定义的,尺寸值也是,这样形成的结果就是,当某些字符串须要修改时,好比要支持国际化,或一些尺寸值须要修改时,一般是不少地方都要修改。所以,就必须规范好,应用界面中的字符串统一在strings.xml中定义,颜色值统一在colors.xml中定义,尺寸值统一在dimens.xml中定义,代码或布局里须要用到的都去引用资源文件相应的字段。
要保持单一性,一定伴随着重构。需求总会变更,代码总会扩展,扩展了慢慢就会破坏原有的单一性,所以就须要重构,再次保持单一性。不断扩展,不断重构,这样才能不断保持良好的单一性。
简洁性
代码最怕的就是臃肿,臃肿的代码可读性差,维护麻烦,扩展更不用说了。没有人会喜欢看臃肿的代码,去维护更痛苦。我看到臃肿的代码,都巴不得即刻进行重构。让代码保持简洁,会让人看得舒服,一目了然,维护和扩展起来也都很是方便。简洁的代码,甚至不须要写注释,只从代码就能让人一眼看懂其作了什么。简洁也并不仅表如今代码上,类、包、资源文件等的命名和组织结构等也一样须要保持简洁。
如何保持简洁?这个问题并无一个标准的答案,但有一个判断是否简洁的简单标准,那就是:直接阅读代码就可以理解代码的意图,若是意图不够明显,那就说明这段代码还不够简洁。类、包、资源文件等等,也是一样的评判标准。下面是我以为对保持简洁有必定做用的一些操做方法。
按照组件类型来分包,而不是按业务模块来分包。业务有可能会变,但组件类型是基本不变的。另外,新加入的开发人员,对业务不熟悉,但对组件是很清楚的,理解快,入手也快。
组件类的命名添加该组件的后缀,例如:Activity类命名添加Activity后缀,Fragment类命令添加Fragment后缀,适配器添加Adapter后缀,等等。实体类则可添加BO的后缀名称,工具类添加util后缀,接口的实现类添加Impl的后缀。接口的命名也同样,好比,个人项目中,接口层的接口后缀都带上了Api,核心层的接口后缀都带Action。
strings.xml文件用来存储应用中的全部字符串,包括页面标题,按钮文字,标签文字,提示文字等等,应该作好分类并统一存放。下面是我推荐的分类方法,若是某个分类的字符串数量太多了,还能够拆分出来放到一个独立的文件,好比页面标题,能够拆分到strings_title.xml文件里,其余资源文件也能够用相似的方式进行处理:
页面标题,命名格式为:title_{页面}
按钮文字,命名格式为:btn_{按钮事件}
标签文字,命名格式为:label_{标签文字}
选项卡文字,命名格式为:tab_{选项卡文字}
消息框文字,命名格式为:toast_{消息}
编辑框的提示文字,命名格式为:hint_{提示信息}
图片的描述文字,命名格式为:desc_{图片文字}
对话框的文字,命名格式为:dialog_{文字}
总结
规范性、单一性、简洁性,这三个基本原则是相辅相成的。单一性和简洁性是规范定义的标准,不能脱离这两个原则去定义规范。而对规范的严格执行,则保证了后两个原则的有效性。