2017年(没有更新很久了,命名规范应该不需要太新)
AS规范:要在IDE设置utf-8,java头部-Dfile.encoding=utf-8;用Optimize Imports删多余导入
命名规范:纯英文
包名规范:全小写,单词连接(com.example.feature);反域名命名规则(顶级->公司->应用->功能)
分包策略:PBF(按功能分包;高内聚低耦合,好维护,抽象清晰,避免命名重复),PBL(按层;分层代码分散,工具类不好管理)
PBF结构:

常量名,类名,方法名,接口,枚举常量同java
Activity/Fragment/Adapter组件类:比如NewsDetailAdapter
工具类/服务类:Utils,Manager,Service结尾
抽象类:Base,Abstract开头
测试类:Test结尾
MVP接口:I开头
非常量名:小驼峰
VO(值对象):小驼峰
DTO(数据传输对象):按接口文档定义的字段名
日志工具类:Logger或LogUtils
字段命名:
非公有字段,非静态字段:m开头(private int mPrivate, int mPrivate, protected int mProtected)
静态字段:开头(private static MyClass sSingleton)
公有非静态字段:小写开头,public int publicField
静态常量:大写,public static final int ABCD = 2;
Type0 控制类型:UI控件很多,避免混淆,所有表示控件的成员变量加上空间缩写(当前缀)


变量名:通义量词,比如mFirstBook,mPreBook,curBook

type1 数据类型:加后缀;如userArr
-
集合加这些:List, Map, Set
-
数组加这些:Arr
-
类型不确定:比如mBooks
参数名:小骆驼
局部变量名:小骆驼
临时变量:整形用i, j, k, m, n;字符型用c,d,e
类型变量名:单大写字母(E,T,可以跟数字T2) 或者 类命名一样格式后面加个T(RequestT)
其他命名格式:看这个 阿里巴巴Java开发手册(详尽版).pdf
代码样式规范:同Java
推荐的写代码时类成员顺序:常量 - 字段 - 构造函数 - override/回调 - public - private - 内部类/IF
override前面加上@override标注
类继承组件的话,override按照生命周期排序写:

函数参数的顺序:Context参数放第一,回调接口参数放最后
public void loadUserAsync(Context context, int userId, UserCallback callback);
字符串常量命名+值:键定义为static final,还要写前缀

比如static final String BUNDLE_AGE = "xxxxx";
Activity,Fragment传参:用Bundle或者Intent时键要static final + 前缀(如上)
因为启动要传参时:用public static启动
AS有成型的模版,不用自己写,启动Activity只用输入starter就可生成启动器:
public static void start(Context context, User user) {
Intent starter = new Intent(context, MainActivity.class);
starter.putParcelableExtra(EXTRA_USER, user);
context.startActivity(starter);
}
这是Fragment的:输入newInstance
public static MainFragment newInstance(User user) {
Bundle args = new Bundle();
args.putParcelable(ARGUMENT_USER, user);
MainFragment fragment = new MainFragment();
fragment.setArguments(args);
return fragment;
}
以上启动器要放在周期onCreate()前面,用extras和arguments的键要private(不暴露给其他类)
行长度限制在100字符
换行同Java
函数链换行:多个函数,太长的时候要换行
Picasso.with(context)
.into(ivAvatar);
多参数换行:
loadPicture(context,
ivAvatar,
"Avatar of the user",
clickListener);
RxJava链式换行:每个操作符都要换行
public Observable<Location> syncLocations() {
return mDatabaseHelper.getAllLocations()
.concatMap(new Func1<Location, Observable<? extends Location>>() {
@Override
public Observable<? extends Location> call(Location location) {
return mRetrofitService.getLocation(location.id);
}
})
.retry(new Func2<Integer, Throwable, Boolean>() {
@Override
public Boolean call(Integer numRetries, Throwable throwable) {
return throwable instanceof RetrofitError;
}
});
}
资源文件:小写+_;比如activity_main.xml
-
组件化开发:组件、公共模块之间创1个UI模块 -> 存资源文件,每个组件依赖此模块(老项目组件化时只用将资源文件放入模块)
-
资源文件分包:还没找到文章(AS对资源进行分包)
-
三方库开发:用到的资源文件+name都要用库名前缀(防止跟其他的资源冲突)
动画资源文件(anim/ 和 animator/):
属性动画文件放res/animator/
视图动画文件放res/anim/
命名:{模块_}逻辑名;{...}可选,逻辑名=单词+_,比如market_cart_add.xml
普通补间动画和属性动画命名:动画类型_方向

颜色资源文件(放在color/):放颜色的资源文件
命名:类型{_模块}_逻辑名,比如sel_btn_font.xml
(可放在res/drawable/,引用时用@drawable,但是不推荐)
图片资源文件:
放在res/drawable/:位图(png等等),可绘制对象资源子类型XML文件
放在res/mipamp/:启动图标
命名:类型{_模块}_逻辑名,类型{_模块}_颜色;后缀加_small是小图,_big是大图


有多种形态的,比如说按钮(sel_btn_xx.xml)的命名:

AS插件SelectorChapek可生成selector
布局资源文件:放在layout/
命名:类型_模块,类型{_模块}_逻辑名

菜单资源文件:放在menu/;比如navigation.xml,main_drawer.xml
命名:{_模块}_逻辑名
values资源文件:放在values/
都是s复数结尾(attrs.xml, colors.xml)-> <resources>标签下标签(如<style>和<color>),要个大xml分成小文件,有多个style或者color文件(styles.xml, styles_home.xml, etc)
colors.xml规范:<color>的name用_命名
<resources>
<!-- grayscale -->
<color name="white" >#FFFFFF</color>
<color name="gray_light">#DBDBDB</color>
<color name="gray" >#939393</color>
<color name="gray_dark" >#5F5F5F</color>
<color name="black" >#323232</color>
<!-- basic colors -->
<color name="green">#27D34D</color>
<color name="blue">#2A91BD</color>
<color name="orange">#FF9D2F</color>
<color name="red">#FF432F</color>
</resources>
如果是主题的颜色:写成colors_theme.xml,其他的同理
dimens.xml规范:同colors.xml;可定义有空隙间隔/字体大小的调色板
写margins和paddings时用spacing_xx布局
strings.xml规范:<string>的name用_命名;{模块名_}逻辑名称

styles.xml规范:用大驼峰,通用style.xml
<style name="ContentText">
<item name="android:textSize">@dimen/font_normal</item>
<item name="android:textColor">@color/basic_black</item>
</style>
应用到TextView:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/price"
style="@style/ContentText"
/>
id命名规则:view 缩写{_模块名}_逻辑名,比如btn_back
项目有黄油刀的话用AS插件ButterKnife Elezny生成注解,没有黄油刀就用A Code Generator插件
版本统一:尚未找到文章
第三方库规范:流行框架速查表(未找到文章),开发人员常用代码(https://github.com/Blankj/AndroidUtilCode)
推荐的轮子(如果不是面试所需,尽量不要闭门造车):
Retrofit:HTTP客户端轮子
RxAndroid:响应编程库(异步任务,事件驱动编程,简化线程操作)
OkHttp:HTTP客户端,网络通信
Glide/Fresco:图片加载缓存框架
Gson/Fastjson:JSON序列化反序列化工具
EventBus/AndroidEventBus:轻量级时间总线框架(发布-订阅模式)
GreenDao:ORM数据库框架
Dagger2(选用):依赖注入框架
Tinker(选用):热修复框架
类注释:作者信息,AS自动写(在Settings/Editor/FileAndCode/Templates/Includes/FileHeader)
/**
* <pre>
* author : Blankj
* e-mail : xxx@xx
* time : 2017/03/07
* desc : xxxx 描述
* version: 1.0
* </pre>
*/
public class WelcomeActivity {
...
}
方法注释:
/**
* bitmap 转 byteArr
*
* @param bitmap bitmap 对象
* @param format 格式
* @return 字节数组
*/
块注释:同Java
其他注释:输入todo,fixme回车就有了
TODO注释:就是解释准备要做什么
FIXME注释:就是标注哪里有错,要修正什么
所有测试要用@Test:
单元测试:比如DatabaseHelperTest(以前考试写的Helper,后面应该加上Test);
模板void methodName 前提条件和预期结果()
比如:void signInWithEmptyEmailFails()
建议测试类分成多个:DataManager分成DataManagerSignInTest, DataManagerLoadUsersTest
Expresso测试:Activity用,比如SignInActivityTest
其他规范:22个
-
合理运用<merge>, <ViewStub>, <include>
-
Activity和Fragment有很多重复操作,用BaseActivity和BaseFragment,然后让所有这些类继承BA和BF
-
数据统一入口:不论什么设计模式都同用一个数据入口,比如http, preference, eventpost, database放在DataManager,只用操作入口DM就行
-
多组合少继承
-
提取方法,去除重复代码(工具类抽取用,可重用)
-
引入Dagger2(ID框架)减少模块耦合;自动生成依赖关系代码
-
引入ReAndroid减少响应式逻辑代码
-
引入事件总线(EventBus, AndroidEventBus, RxBus):可以子DataLayer发送时间(ViewLayer组件方便订阅事件,减少回调)
-
尽量用局部变量
-
一定要close流
-
尽量减少变量重复计算(下面有详解)
-
尽量懒加载策略,需要的时候再创
-
其他的没问题就省略了
-
循环内不用try+catch,放外层
-
IO操作用缓冲IO流
-
尽量用HashMap,ArrayList,StringBuilder,不推荐HashTable,Vector,StringBuffer
-
尽量在合适场合中用单例
-
基本数据类型转String:用toString()最快,valueOf()中,concat+最慢
-
用Lint优化代码结构:右键module-目录-Analyze-InspectCode
-
一定要内存泄漏检测
尽量减少变量重复计算:
for (int i = 0; i < list.size(); i++) {
...
}
写成
for (int i = 0, len = list.size(); i < len; i++) {
...
}
尽量懒加载:
String str = "aaa";
if (i==1){
list.add(str);
}
写成
if(i==1){
String str = "aa";
list.add(str);
}