參考文章:http://keeganlee.me/post/android/20150709 http://www.reibang.com/p/0a984f999592
https://source.android.com/source/code-style
源文件結(jié)構(gòu)規(guī)范
一個(gè)源文件包含(按順序地):
- 許可證或版權(quán)信息(如有需要)
- package語句
- import語句
- 一個(gè)頂級(jí)類(只有一個(gè))以上每個(gè)部分之間用一個(gè)空行隔開渐扮。
許可證或版權(quán)信息
如果一個(gè)文件包含許可證或版權(quán)信息无午,那么它應(yīng)當(dāng)被放在文件最前面。
package語句
package 語句不換行,列限制并不適用于package語句愕撰。(即package語句寫在一行里)
import語句
import不要使用通配符
即,不要出現(xiàn)類似這樣的import語句:import java.util.*;
不要換行
import語句不換行,列限制并不適用于import語句。(每個(gè)import語句獨(dú)立成行)
順序和間距
import語句可分為以下幾組具则,按照這個(gè)順序,每組由一個(gè)空行分隔:
- 導(dǎo)入 Android 包
- 導(dǎo)入第三方包(com具帮、junit博肋、net低斋、org)
- java 和 javax
類聲明
只有一個(gè)頂級(jí)
類聲明每個(gè)頂級(jí)類都在一個(gè)與它同名的源文件中(當(dāng)然,還包含.java后綴)匪凡。
類成員順序
類的成員順序?qū)σ讓W(xué)性有很大的影響膊畴,但這也不存在唯一的通用法則。不同的類對(duì)成員的排序可能是不同的病游。
最重要的一點(diǎn)唇跨,每個(gè)類應(yīng)該以某種邏輯去排序它的成員,維護(hù)者應(yīng)該要能解釋這種排序邏輯衬衬。比如买猖, 新的方法不能總是習(xí)慣性地添加到類的結(jié)尾,因?yàn)檫@樣就是按時(shí)間順序而非某種邏輯來排序的佣耐。
區(qū)塊劃分
建議使用注釋將源文件分為明顯的區(qū)塊政勃,區(qū)塊劃分如下
- 常量聲明區(qū)
- UI控件成員變量聲明區(qū)
- 普通成員變量聲明區(qū)
- 內(nèi)部接口聲明區(qū)
- 初始化相關(guān)方法區(qū)
- 事件響應(yīng)方法區(qū)
- 普通邏輯方法區(qū)
- 重載的邏輯方法區(qū)
- 發(fā)起異步任務(wù)方法區(qū)
- 異步任務(wù)回調(diào)方法區(qū)
- 生命周期回調(diào)方法區(qū)(出去onCreate()方法)
- 內(nèi)部類聲明區(qū)
重載:永不分離
當(dāng)一個(gè)類有多個(gè)構(gòu)造函數(shù)唧龄,或是多個(gè)同名方法兼砖,這些函數(shù)/方法應(yīng)該按順序出現(xiàn)在一起,中間不要放進(jìn)其它函數(shù)/方法既棺。
注釋規(guī)范
文件頭注釋
文件頭注釋使用以下格式讽挟,需要將版權(quán)聲明進(jìn)行替換
/**
* Copyright (C) 2017 zhangyang. All rights reserved.
*
* @Package: ${PACKAGE_NAME}
* @Description:
* @author ${USER}
* @date ${TIME}
*/
在android studio中的配置方法為:
類和接口注釋
類和接口的注釋使用以下的注釋格式:
/**
* @description $description$
* @author $user$
* @time $date$ $time$
*/
在android studio中的配置方式如下,首先選擇Editor->Live Templates,然后選擇右側(cè)的加號(hào)丸冕,選擇Template Group耽梅,命名為custom,再點(diǎn)擊加號(hào)胖烛,選擇Live Template眼姐,命名為cmc(cmc是快捷鍵,可以自己任意命名)佩番,然后可以對(duì)該自定義模板進(jìn)行描述众旗,并選擇應(yīng)用的場(chǎng)景為java->Declaration,詳見下面的第二幅圖趟畏。最后注意需要點(diǎn)擊Edit variables贡歧,對(duì)相應(yīng)的值配置由程序動(dòng)態(tài)賦值,例如$user$赋秀,配置為user()利朵,即使用當(dāng)前計(jì)算機(jī)用戶名,減少工作量猎莲。
方法注釋
方法注釋采用如下格式:
/**
* @description 用戶注冊(cè)
* @author zhangyang
* @time 2017/6/19 上午9:38
* @param userName 用戶名
* @param password 密碼
* @return
*/
public int registerUser(String userName, String password);
在android studio中的配置方式與上面的類和接口的配置方式相同:
/**
* @description $description$
* @author $user$
* @time $date$ $time$
* @param $param$
* @return $return$
*/
這里我命名快捷鍵為cmf绍弟。注意:在android studio里面沒有找到自定義模板自動(dòng)生成參數(shù)的方案,如果使用默認(rèn)的方法生成注釋方案著洼,則除了參數(shù)不能增加其他的自定義字段樟遣。因此需要編寫代碼時(shí)姥份,在相應(yīng)方法上輸入cmf生成注釋后,還需要手動(dòng)編輯@param年碘,有幾個(gè)參數(shù)需要編輯幾個(gè)澈歉。
變量和常量注釋
下面幾種情況下的常量和變量,都要添加注釋說明屿衅,在上方添加注釋埃难。//和內(nèi)容后面有一個(gè)空格。
- 接口中定義的所有常量
- 公有類的公有常量
- 枚舉類定義的所有枚舉常量
- 實(shí)體類的所有屬性變量
// 普通用戶
public static final int TYPE_COMMON_USER = 1;
// 管理員用戶
public static final int TYPE_ADMIN_USER = 2;
書寫規(guī)范
編碼方式
編碼方式統(tǒng)一用UTF-8. Android Studio默認(rèn)已是UTF-8涤久,只要不去改動(dòng)它就可以了涡尘。
縮進(jìn)
縮進(jìn)統(tǒng)一為4個(gè)空格
花括號(hào)書寫
- 左大括號(hào)前不換行
- 左大括號(hào)后換行
- 右大括號(hào)前換行
- 如果右大括號(hào)是一個(gè)語句、函數(shù)體或類的終止响迂,則右大括號(hào)后換行; 否則不換行
例如考抄,如果右大括號(hào)后面是else或逗號(hào),則不換行蔗彤。
return new MyClass() {
@Override public void method() {
if (condition()) {
try {
something();
} catch (ProblemException e) {
recover();
}
}
}
};
空格的使用
if川梅、else、for然遏、switch贫途、while等邏輯關(guān)鍵字與后面的語句留一個(gè)空格隔開。
if (booleanVariable) {
// TODO while booleanVariable is true
} else {
// TODO else
}
運(yùn)算符兩邊各用一個(gè)空格隔開待侵。
int result = a + b; //Good, = 和 + 兩邊各用一個(gè)空格隔開
int result=a+b; //Bad,=和+兩邊沒用空格隔開
方法的每個(gè)參數(shù)之間用一個(gè)空格隔開丢早。
public void method(String param1, String param2); // Good,param1后面的逗號(hào)與String之間隔了一個(gè)空格
method(param1, param2); // Good秧倾,方法調(diào)用時(shí)怨酝,param1后面的逗號(hào)與param2之間隔了一個(gè)空格
method(param1,param2); // Bad,沒有用一個(gè)空格隔開
空行的使用
將邏輯相關(guān)的代碼段用空行隔開那先,以提高可讀性农猬。空行也只空一行胃榕,不要空多行盛险。在以下情況需用一個(gè)空行:
- 兩個(gè)方法之間
- 方法內(nèi)的兩個(gè)邏輯段之間
- 方法內(nèi)的局部變量和方法的第一條邏輯語句之間
- 常量和變量之間
表達(dá)式過長(zhǎng)書寫
當(dāng)一個(gè)表達(dá)式無法容納在一行內(nèi)時(shí),可換行顯示勋又,另起的新行用8個(gè)空格縮進(jìn)苦掘。
someMethod(longExpression1, longExpression2, longExpression3,
longExpression4, longExpression5);
變量聲明
一行聲明一個(gè)變量,不要一行聲明多個(gè)變量楔壤,這樣有利于寫注釋鹤啡。
// 參數(shù)1
private String param1;
// 參數(shù)2
private String param2;
行寬設(shè)置
行寬設(shè)置為100,設(shè)置格式化時(shí)自動(dòng)斷行到行寬位置蹲嚣。
方法規(guī)模
一個(gè)方法最多不要超過40行代碼(官方建議)递瑰。
常量定義
常量統(tǒng)一采用接口來定義祟牲,按模塊和類型等劃分。
文字和元素大小單位定義
官方建議文字大小的單位統(tǒng)一用sp抖部,元素大小的單位統(tǒng)一用dp说贝。從實(shí)際開發(fā)中看,文字大小采用sp慎颗,會(huì)導(dǎo)致文字大小隨著系統(tǒng)設(shè)置字體的大小變化乡恕,導(dǎo)致布局出問題。因此我們項(xiàng)目組初期采用的都是使用dp俯萎,但目前使用的是以1280*720基準(zhǔn)尺寸傲宜,橫坐標(biāo)分成1280份,縱坐標(biāo)分成720份夫啊,其他按比例進(jìn)行伸縮函卒,實(shí)際是以px為單位處理。
字符串定義
應(yīng)用中的字符串統(tǒng)一在strings.xml中定義撇眯,然后在代碼和布局文件中引用报嵌。
顏色定義
顏色值統(tǒng)一在colors.xml中定義,然后在代碼和布局文件中引用叛本。另外沪蓬,不要在代碼和布局文件中引用系統(tǒng)的顏色,除了透明来候。
命名規(guī)范
包命名
域名反寫+項(xiàng)目名稱+模塊名稱,全部單詞用小寫字母逸雹。
例如
com.android.example.login
類和接口命名
使用大駝峰規(guī)則营搅,用名詞或名詞詞組命名,每個(gè)單詞的首字母大寫梆砸。
以下為幾種常用類的命名:
- activity類转质,命名以Activity為后綴,如:LoginActivity
- fragment類帖世,命名以Fragment為后綴休蟹,如:ShareDialogFragment
- service類,命名以Service為后綴日矫,如:DownloadService
- adapter類赂弓,命名以Adapter為后綴,如:CouponListAdapter
- 工具類哪轿,命名以Util為后綴盈魁,如:EncryptUtil
- 模型類,命名以Model為后綴窃诉,如:LoginModel
- 接口實(shí)現(xiàn)類杨耙,命名以Impl為后綴赤套,如:ApiImpl
方法命名
使用小駝峰規(guī)則,用動(dòng)詞命名珊膜,第一個(gè)單詞的首字母小寫容握,其他單詞的首字母大寫。
以下為幾種常用方法的命名:
- 初始化方法车柠,命名以init開頭唯沮,例:initView
- 按鈕點(diǎn)擊方法,命名以onClick開頭堪遂,例:onclickLogin
- 設(shè)置方法介蛉,命名以set開頭,例:setData
- 具有返回值的獲取方法溶褪,命名以get開頭币旧,例:getData
- 通過異步加載數(shù)據(jù)的方法,命名以load開頭猿妈,例:loadData
- 布爾型的判斷方法吹菱,命名以is或has,或具有邏輯意義的單詞如equals彭则,例:isEmpty
控件縮寫
控件 | 縮寫 | 控件 | 縮寫 |
---|---|---|---|
TextView | TV | EditText | ET |
Button | Btn | ImageButton | IBt |
ImageView | IV | ListView | LV |
ProgressBar | PB | SeekBar | SB |
CheckBox | CB | LinearLayout | LL |
Relativelayout | RL | FrameLayout | FL |
ScrollView | SV | GridView | GV |
常量命名
全部為大寫單詞鳍刷,單詞之間用下劃線分開。
public final static int PAGE_SIZE = 20;
變量命名
{范圍描述+}意義描述+類型描述的組合俯抖,用駝峰式输瓜,首字母小寫
- 非公開且非靜態(tài)字段的名稱以 m 開頭。
- 靜態(tài)字段的名稱以 s 開頭芬萍。
- 其他字段以小寫字母開頭尤揣。
- 公開靜態(tài) final 字段(常量)為全部大寫并用下劃線連接 (ALL_CAPS_WITH_UNDERSCORES)。
例如:
public class MyClass {
public static final int SOME_CONSTANT = 42;
public int publicField;
private static MyClass sSingleton;
int mPackagePrivate;
private int mPrivate;
protected int mProtected;
}
控件id命名
控件縮寫{范圍}意義柬祠,范圍可選北戏,只在有明確定義的范圍內(nèi)才需要加上。
<!-- 這是標(biāo)題欄的標(biāo)題 -->
<TextView
android:id="@+id/tv_header_title"
... />
<!-- 這是登錄按鈕 -->
<Button
android:id="@+id/btn_login"
... />
layout命名
組件類型{范圍}功能漫蛔,范圍可選嗜愈,只在有明確定義的范圍內(nèi)才需要加上。
以下為幾種常用的組件類型命名:
- activity_{范圍_}功能莽龟,為Activity的命名格式
- fragment_{范圍_}功能蠕嫁,為Fragment的命名格式
- dialog_{范圍_}功能,為Dialog的命名格式
- item_list_{范圍_}功能轧房,為L(zhǎng)istView的item命名格式
- item_grid_{范圍_}功能拌阴,為GridView的item命名格式
- header_list_{范圍_}功能,為L(zhǎng)istView的HeaderView命名格式
- footer_list_{范圍_}功能奶镶,為L(zhǎng)istView的FooterView命名格式
strings的命名
模塊類型{范圍_}功能迟赃,范圍可選陪拘。
以下為幾種常用的命名(以登錄模塊為例):
- 頁面標(biāo)題,命名格式為:login_title_頁面
- 按鈕文字纤壁,命名格式為:login_btn_按鈕事件
- 標(biāo)簽文字左刽,命名格式為:login_label_標(biāo)簽文字
- 選項(xiàng)卡文字,命名格式為:login_tab_選項(xiàng)卡文字
- 消息框文字酌媒,命名格式為:login_toast_消息
- 編輯框的提示文字欠痴,命名格式為:login_hint_提示信息
- 圖片的描述文字,命名格式為:login_desc_圖片文字
- 對(duì)話框的文字秒咨,命名格式為:login_dialog_文字
- menu的item文字喇辽,命名格式為:login_action_文字
colors的命名
前綴{控件}{范圍}{_后綴},控件雨席、范圍菩咨、后綴可選,但控件和范圍至少要有一個(gè)陡厘。例如bg_btn_send_normal
- 背景顏色抽米,添加bg前綴
- 文本顏色,添加text前綴
- 分割線顏色糙置,添加div前綴
- 公共的顏色云茸,添加common前綴
- 區(qū)分狀態(tài)時(shí),默認(rèn)狀態(tài)的顏色谤饭,添加normal后綴
- 區(qū)分狀態(tài)時(shí)标捺,按下時(shí)的顏色,添加pressed后綴
- 區(qū)分狀態(tài)時(shí)网持,選中時(shí)的顏色宜岛,添加selected后綴
- 區(qū)分狀態(tài)時(shí),不可用時(shí)的顏色功舀,添加disable后綴
drawable的命名
前綴{控件}{范圍}{_后綴},控件身弊、范圍辟汰、后綴可選,但控件和范圍至少要有一個(gè)阱佛。
- 圖標(biāo)類帖汞,添加ic前綴
- 背景類,添加bg前綴
- 分隔類凑术,添加div前綴
- 默認(rèn)類翩蘸,添加def前綴
- 區(qū)分狀態(tài)時(shí),默認(rèn)狀態(tài)淮逊,添加normal后綴
- 區(qū)分狀態(tài)時(shí)催首,按下時(shí)的狀態(tài)扶踊,添加pressed后綴
- 區(qū)分狀態(tài)時(shí),選中時(shí)的狀態(tài)郎任,添加selected后綴
- 區(qū)分狀態(tài)時(shí)秧耗,不可用時(shí)的狀態(tài),添加disable后綴
- 多種狀態(tài)的舶治,添加selector后綴(一般為L(zhǎng)istView的selector或按鈕的selector)
動(dòng)畫文件命名
動(dòng)畫類型_動(dòng)畫方向分井。
- fade_in,淡入
- fade_out霉猛,淡出
- push_down_in尺锚,從下方推入
- push_down_out,從下方推出
- slide_in_from_top惜浅,從頭部滑動(dòng)進(jìn)入
- zoom_enter瘫辩,變形進(jìn)入
- shrink_to_middle,中間縮小
編程實(shí)踐
@Override:能用則用
只要是合法的赡矢,就把@Override注解給用上杭朱。
捕獲的異常:不能忽視
除了下面的例子,對(duì)捕獲的異常不做響應(yīng)是極少正確的吹散。(典型的響應(yīng)方式是打印日志弧械,或者如果它被認(rèn)為是不可能的,則把它當(dāng)作一個(gè) AssertionError 重新拋出空民。)
如果它確實(shí)是不需要在catch塊中做任何響應(yīng)刃唐,需要做注釋加以說明(如下面的例子)。
try {
int i = Integer.parseInt(response);
return handleNumericResponse();
} catch (NumberFormatException ok) {
// it's not numeric; that's fine, just continue
}
return handleTextResponse(response);
例外:在測(cè)試中界轩,如果一個(gè)捕獲的異常被命名為expected画饥,則它可以被不加注釋地忽略。下面是一種非常常見的情形浊猾,用以確保所測(cè)試的方法會(huì)拋出一個(gè)期望中的異常抖甘,因此在這里就沒有必要加注釋。
try {
emptyStack.pop();
fail();
} catch (NoSuchElementException expected) {
}
使用 TODO 備注
為代碼使用 TODO 備注是短期的臨時(shí)解決方案葫慎,或者說足夠好但并不完美衔彻。TODO 備注應(yīng)該以全部大寫的字符串 TODO 開頭,后跟一個(gè)冒號(hào):
// TODO: Remove this code after the UrlTable2 has been checked in.
和
// TODO: Change this to use a flag instead of a constant.
如果TODO 采用“在未來的某個(gè)日期做某事”的形式偷办,請(qǐng)確保在其中包含一個(gè)非常具體的日期(“在 2005 年 11 月前修復(fù)”)或者一個(gè)非常具體的事件(“在所有生產(chǎn)環(huán)境合成器都可處理 V7 協(xié)議后移除此代碼”)艰额。
靜態(tài)成員:使用類進(jìn)行調(diào)用
使用類名調(diào)用靜態(tài)的類成員,而不是具體某個(gè)對(duì)象或表達(dá)式椒涯。
Foo aFoo = ...;
Foo.aStaticMethod(); // good
aFoo.aStaticMethod(); // bad
somethingThatYieldsAFoo().aStaticMethod(); // very bad
Finalizers: 禁用
極少會(huì)去重載Object.finalize柄沮。
Tip:
不要使用finalize。如果你非要使用它,請(qǐng)先仔細(xì)閱讀和理解Effective Java第7條款:"Avoid Finalizers"祖搓,然后不要使用它狱意。
謹(jǐn)慎使用日志記錄
項(xiàng)目中請(qǐng)不要直接使用Log打印日志,應(yīng)該至少對(duì)系統(tǒng)日志封裝一個(gè)日志類棕硫,該類可以控制當(dāng)前打印輸出的日志級(jí)別或者打開和關(guān)閉日志打印髓涯。每個(gè)類定義一個(gè)常量TAG用來打印相應(yīng)的類的日志,當(dāng)功能開發(fā)穩(wěn)定之后哈扮,請(qǐng)去掉開發(fā)打印的調(diào)試日志纬纪。
保持一致
總而言之:保持一致。如果正在修改代碼滑肉,花幾分鐘時(shí)間看一下周圍的代碼并確定其樣式包各。如果該代碼在 if 語句周圍使用空格,那么您也應(yīng)該這樣做靶庙。如果代碼備注的周圍是用星號(hào)組成的小方框问畅,您也應(yīng)該將備注放在這樣的小方框內(nèi)。