最全面的 Android 編碼規範指南

李旺成發表於2016-04-21

1. 前言

這份文件參考了 Google Java 程式設計風格規範Google 官方 Android 編碼風格規範。該文件僅供參考,只要形成一個統一的風格,見量知其意就可。

1.1 術語說明

在本文件中,除非另有說明:

  1. 術語 class 可表示一個普通類,列舉類,介面或是annotation型別(@interface)
  2. 術語 comment 只用來指代實現的註釋(implementation comments),我們不使用”documentation comments”一詞,而是用 Javadoc。其他的術語說明會偶爾在後面的文件出現。

1.2 指南說明本文件中的示例程式碼並不作為規範,僅供參考。

基本格式方面使用 AndroidStudio 預設模板即可(使用格式化快捷鍵處理後基本符合)。

2. 原始檔基礎

2.1 檔名

原始檔以其最頂層的類名來命名,大小寫敏感,副檔名為.java。

2.2 檔案編碼:UTF-8

原始檔編碼格式為 UTF-8。

2.3 特殊字元

2.3.1 空白字元

除了行結束符序列,ASCII水平空格字元(0×20,即空格)是原始檔中唯一允許出現的空白字元,這意味著:

  1. 所有其它字串中的空白字元都要進行轉義。
  2. 製表符不用於縮排(可以在IDE中Tab鍵設定為若干個空格)。

2.3.2 特殊轉義序列

對於具有特殊轉義序列的任何字元(\b, \t, \n, \f, \r, \”, \’及),我們使用它的轉義序列,而不是相應的八進位制(比如\012)或Unicode(比如\u000a)轉義。

2.3.3 非ASCII字元

對於剩餘的非ASCII字元,是使用實際的Unicode字元(比如∞),還是使用等價的Unicode轉義符(比如\u221e),取決於哪個能讓程式碼更易於閱讀和理解。

Tip:在使用Unicode轉義符或是一些實際的Unicode字元時,建議做些註釋給出解釋,這有助於別人閱讀和理解。

例如:

String unitAbbrev = "μs"; | 贊,即使沒有註釋也非常清晰
String unitAbbrev = "\u03bcs"; // "μs" | 允許,但沒有理由要這樣做
String unitAbbrev = "\u03bcs"; // Greek letter mu, "s" | 允許,但這樣做顯得笨拙還容易出錯
String unitAbbrev = "\u03bcs"; | 很糟,讀者根本看不出這是什麼
return '\ufeff' + content; // byte order mark | Good,對於非列印字元,使用轉義,並在必要時寫上註釋

Tip:永遠不要由於害怕某些程式可能無法正確處理非ASCII字元而讓你的程式碼可讀性變差。當程式無法正確處理非ASCII字元時,它自然無法正確執行, 你就會去fix這些問題的了。(言下之意就是大膽去用非ASCII字元,如果真的有需要的話)

3. 原始檔結構

一個原始檔包含(按順序地):

  1. 許可證或版權資訊(如有需要)
  2. package語句
  3. import語句
  4. 一個頂級類(只有一個)以上每個部分之間用一個空行隔開。

3.1 許可證或版權資訊

如果一個檔案包含許可證或版權資訊,那麼它應當被放在檔案最前面。

3.2 package語句

package 語句不換行,列限制(4.4節)並不適用於package語句。(即package語句寫在一行裡)

3.3 import語句

3.3.1 import不要使用萬用字元

即,不要出現類似這樣的import語句:import java.util.*;

3.3.2 不要換行

import語句不換行,列限制(4.4節)並不適用於import語句。(每個import語句獨立成行)

3.3.3 順序和間距

import語句可分為以下幾組,按照這個順序,每組由一個空行分隔:

  1. 所有的靜態匯入獨立成組
  2. com.google imports(僅當這個原始檔是在com.google包下)
  3. 第三方的包。每個頂級包為一組,字典序。例如:android, com, junit, org, sun
  4. java imports5.javax imports組內不空行,按字典序排列。

3.4 類宣告

3.4.1 只有一個頂級

類宣告每個頂級類都在一個與它同名的原始檔中(當然,還包含.java字尾)。
例外:package-info.java,該檔案中可沒有package-info類。

3.4.2 類成員順序

類的成員順序對易學性有很大的影響,但這也不存在唯一的通用法則。不同的類對成員的排序可能是不同的。

最重要的一點,每個類應該以某種邏輯去排序它的成員,維護者應該要能解釋這種排序邏輯。比如, 新的方法不能總是習慣性地新增到類的結尾,因為這樣就是按時間順序而非某種邏輯來排序的。

3.4.2.1 區塊劃分

建議使用註釋將原始檔分為明顯的區塊,區塊劃分如下

  1. 常量宣告區
  2. UI控制元件成員變數宣告區
  3. 普通成員變數宣告區
  4. 內部介面宣告區
  5. 初始化相關方法區
  6. 事件響應方法區
  7. 普通邏輯方法區
  8. 過載的邏輯方法區
  9. 發起非同步任務方法區
  10. 非同步任務回撥方法區
  11. 生命週期回撥方法區(出去onCreate()方法)
  12. 內部類宣告區

3.4.2.2 類成員排列通用規則

  1. 按照發生的先後順序排列
  2. 常量按照使用先後排列
  3. UI控制元件成員變數按照layout檔案中的先後順序排列
  4. 普通成員變數按照使用的先後順序排列
  5. 方法基本上都按照呼叫的先後順序在各自區塊中排列
  6. 相關功能作為小區塊放在一起(或者封裝掉)

3.4.2.3 過載:永不分離

當一個類有多個建構函式,或是多個同名方法,這些函式/方法應該按順序出現在一起,中間不要放進其它函式/方法。

4. 格式術語

說明:塊狀結構(block-like construct)指的是一個類,方法或建構函式的主體。需要注意的是,陣列初始化中的初始值可被選擇性地視為塊狀結構(4.8.3.1節)。

4.1 大括號

4.1.1 使用大括號(即使是可選的)

大括號與if, else, for, do, while語句一起使用,即使只有一條語句(或是空),也應該把大括號寫上。

4.1.2 非空塊:K & R 風格

對於非空塊和塊狀結構,大括號遵循 Kernighan 和 Ritchie 風格 (Egyptian brackets):

  • 左大括號前不換行
  • 左大括號後換行
  • 右大括號前換行
  • 如果右大括號是一個語句、函式體或類的終止,則右大括號後換行; 否則不換行。

例如,如果右大括號後面是else或逗號,則不換行。

示例:

return new MyClass() {    
    @Override public void method() {        
        if (condition()) {
            try {
                something();
            } catch (ProblemException e) {
                recover();
            }
        }
    }
};

4.8.1節給出了enum類的一些例外。

4.1.3 空塊:可以用簡潔版本

一個空的塊狀結構裡什麼也不包含,大括號可以簡潔地寫成{},不需要換行。

例外:如果它是一個多塊語句的一部分(if/else 或 try/catch/finally) ,即使大括號內沒內容,右大括號也要換行。
示例:

void doNothing() {}

4.2 塊縮排:4個空格

每當開始一個新的塊,縮排增加4個空格,當塊結束時,縮排返回先前的縮排級別。縮排級別適用於程式碼和註釋。(見4.1.2節中的程式碼示例)

4.3 一行一個語句

每個語句後要換行。

4.4 列限制:80或100

一個專案可以選擇一行80個字元或100個字元的列限制,除了下述例外,任何一行如果超過這個字元數限制,必須自動換行。

例外:

  • 不可能滿足列限制的行(例如,Javadoc中的一個長URL,或是一個長的JSNI方法參考)。
  • package和import語句(見3.2節和3.3節)。
  • 註釋中那些可能被剪下並貼上到shell中的命令列。

4.5 自動換行

術語說明:一般情況下,一行長程式碼為了避免超出列限制(80或100個字元)而被分為多行,我們稱之為自動換行(line-wrapping)。我們並沒有全面,確定性的準則來決定在每一種情況下如何自動換行。很多時候,對於同一段程式碼會有好幾種有效的自動換行方式。

Tip:提取方法或區域性變數可以在不換行的情況下解決程式碼過長的問題(是合理縮短命名長度吧)

4.5.1 從哪裡斷開

自動換行的基本準則是:更傾向於在更高的語法級別處斷開。

  1. 如果在非賦值運算子處斷開,那麼在該符號前斷開(比如+,它將位於下一行)。注意:這一點與 Google 其它語言的程式設計風格不同(如 C++ 和 JavaScript )。
  2. 這條規則也適用於以下”類運算子”符號:點分隔符(.),型別界限中的 &(),catch 塊中的管道符號(catch (FooException | BarException e)
  3. 如果在賦值運算子處斷開,通常的做法是在該符號後斷開(比如=,它與前面的內容留在同一行)。這條規則也適用於foreach語句中的分號。
  4. 方法名或建構函式名與左括號留在同一行。
  5. 逗號(,)與其前面的內容留在同一行。

4.5.2 自動換行時縮排至少+8個空格

自動換行時,第一行後的每一行至少比第一行多縮排8個空格(注意:製表符不用於縮排。見2.3.1節)。當存在連續自動換行時,縮排可能會多縮排不只8個空格(語法元素存在多級時)。一般而言,兩個連續行使用相同的縮排當且僅當它們開始於同級語法元素。

第4.6.3水平對齊一節中指出,不鼓勵使用可變數目的空格來對齊前面行的符號。

4.6 空白

4.6.1 垂直空白

以下情況需要使用一個空行:

  1. 類內連續的成員之間:欄位,建構函式,方法,巢狀類,靜態初始化塊,例項初始化塊。 例外: 兩個連續欄位之間的空行是可選的,用於欄位的空行主要用來對欄位進行邏輯分組。
  2. 在函式體內,語句的邏輯分組間使用空行。
  3. 類內的第一個成員前或最後一個成員後的空行是可選的(既不鼓勵也不反對這樣做,視個人喜好而定)。
  4. 要滿足本文件中其他節的空行要求(比如3.3節:import語句)
  5. 多個連續的空行是允許的,但沒有必要這樣做(我們也不鼓勵這樣做)。

4.6.2 水平空白

除了語言需求和其它規則,並且除了文字,註釋和Javadoc用到單個空格,單個ASCII空格也出現在以下幾個地方:

  1. 分隔任何保留字與緊隨其後的左括號(()(如if, for catch等)。
  2. 分隔任何保留字與其前面的右大括號(})(如else, catch)。
  3. 在任何左大括號前({),兩個例外:
    o @SomeAnnotation({a, b})(不使用空格)。
    o String[][] x = foo;(大括號間沒有空格,見下面的Note)。
  4. 在任何二元或三元運算子的兩側。這也適用於以下”類運算子”符號:
    o 型別界限中的&()。
    o catch塊中的管道符號(catch (FooException | BarException e)。
    o foreach語句中的分號。
  5. 在, : ;及右括號())後
  6. 如果在一條語句後做註釋,則雙斜槓(//)兩邊都要空格。這裡可以允許多個空格,但沒有必要。
  7. 型別和變數之間:List list。
  8. 陣列初始化中,大括號內的空格是可選的,即new int[] {5, 6}和new int[] { 5, 6 }都是可以的。

Note:這個規則並不要求或禁止一行的開關或結尾需要額外的空格,只對內部空格做要求。

4.6.3 水平對齊:不做要求

術語說明:水平對齊指的是通過增加可變數量的空格來使某一行的字元與上一行的相應字元對齊。
這是允許的(而且在不少地方可以看到這樣的程式碼),但Google程式設計風格對此不做要求。即使對於已經使用水平對齊的程式碼,我們也不需要去保持這種風格。

以下示例先展示未對齊的程式碼,然後是對齊的程式碼:

private int x; // this is fine
private Color color; // this too

private int    x;         // permitted, but future edits
private Color  color;     // may leave it unaligned

Tip:對齊可增加程式碼可讀性,但它為日後的維護帶來問題。考慮未來某個時候,我們需要修改一堆對齊的程式碼中的一行。
這可能導致原本很漂亮的對齊程式碼變得錯位。很可能它會提示你調整週圍程式碼的空白來使這一堆程式碼重新水平對齊(比如程式設計師想保持這種水平對齊的風格)。
這就會讓你做許多的無用功,增加了reviewer的工作並且可能導致更多的合併衝突。

4.7 用小括號來限定組:推薦

除非作者和reviewer都認為去掉小括號也不會使程式碼被誤解,或是去掉小括號能讓程式碼更易於閱讀,否則我們不應該去掉小括號。

我們沒有理由假設讀者能記住整個Java運算子優先順序表。

4.8 具體結構

4.8.1 列舉類

列舉常量間用逗號隔開,換行可選。

沒有方法和文件的列舉類可寫成陣列初始化的格式:

private enum Suit { 
    CLUBS, 
    HEARTS, 
    SPADES, 
    DIAMONDS
}

由於列舉類也是一個類,因此所有適用於其它類的格式規則也適用於列舉類。

4.8.2 變數宣告

4.8.2.1 每次只宣告一個變數

不要使用組合宣告,比如int a, b;。

4.8.2.2 需要時才宣告,並儘快進行初始化

不要在一個程式碼塊的開頭把區域性變數一次性都宣告瞭(這是c語言的做法),而是在第一次需要使用它時才宣告。 區域性變數在宣告時最好就進行初始化,或者宣告後儘快進行初始化。

4.8.3 陣列

4.8.3.1 陣列初始化:可寫成塊狀結構

陣列初始化可以寫成塊狀結構,比如,下面的寫法都是OK的:

new int[] {
        0, 1, 2, 3 
}
new int[] {
        0,
        1,
        2,
        3
}
new int[] {
        0, 1,
        2, 3
}
new int[]
        {0, 1, 2, 3}

4.8.3.2 非C風格的陣列宣告

中括號是型別的一部分:String[] args, 而非 String args[]。

4.8.4 switch語句

術語說明:switch塊的大括號內是一個或多個語句組。
每個語句組包含一個或多個switch標籤(case FOO:或default:),後面跟著一條或多條語句。

4.8.4.1 縮排

與其它塊狀結構一致,switch塊中的內容縮排為2個空格。每個switch標籤後新起一行,再縮排2個空格,寫下一條或多條語句。

4.8.4.2 Fall-through:註釋

在一個switch塊內,每個語句組要麼通過break, continue, return或丟擲異常來終止,要麼通過一條註釋來說明程式將繼續執行到下一個語句組, 任何能表達這個意思的註釋都是OK的(典型的是用// fall through)。這個特殊的註釋並不需要在最後一個語句組(一般是default)中出現。

示例:

switch (input) {
    case 1:
    case 2:
        prepareOneOrTwo();        // fall through
    case 3:
        handleOneTwoOrThree();
        break;
    default:
        handleLargeNumber(input);
}

4.8.4.3 default的情況要寫出來

每個switch語句都包含一個default語句組,即使它什麼程式碼也不包含。

4.8.5 註解(Annotations)

註解緊跟在文件塊後面,應用於類、方法和建構函式,一個註解獨佔一行。這些換行不屬於自動換行(第4.5節,自動換行),因此縮排級別不變。

例如:

@Nullable public String getNameIfPresent() { … }

例外:單個的註解可以和簽名的第一行出現在同一行。

例如:

@Override public int hashCode() { … }應用於欄位的註解緊隨文件塊出現,應用於欄位的多個註解允許與欄位出現在同一行。

例如:

@Partial @Mock DataLoader loader;

引數和區域性變數註解沒有特定規則。

4.8.6 註釋

4.8.6.1 塊註釋風格

塊註釋與其周圍的程式碼在同一縮排級別。它們可以是//風格,也可以是// …風格。對於多行的//註釋,後續行必須從開始, 並且與前一行的對齊。

以下示例註釋都是OK的。

/** This is // And so /* Or you can
 *  okay. // is this. * even do this. */
 */

註釋不要封閉在由星號或其它字元繪製的框架裡。

Tip:在寫多行註釋時,如果你希望在必要時能重新換行(即註釋像段落風格一樣),那麼使用//。

4.8.7 Modifiers

類和成員的modifiers如果存在,則按Java語言規範中推薦的順序出現。

public protected private abstract static final transient Volatile synchronized native strictfp

5. 命名約定

5.1 對所有識別符號都通用的規則

識別符號只能使用ASCII字母和數字,因此每個有效的識別符號名稱都能匹配正規表示式\w+。

5.2 識別符號型別的規則

5.2.1 包名

包名全部小寫,連續的單詞只是簡單地連線起來,不使用下劃線。

採用反域名命名規則,全部使用小寫字母。一級包名為com,二級包名為xx(可以是公司或則個人的隨便),三級包名根據應用進行命名,四級包名為模組名或層級名。

例如:com.jiashuangkuaizi.kitchen

包名 此包中包含
com.xx.應用名稱縮寫.activity 頁面用到的Activity類 (activitie層級名使用者介面層)
com.xx.應用名稱縮寫.base 基礎共享的類
com.xx.應用名稱縮寫.adapter 頁面用到的Adapter類 (介面卡的類)
com.xx.應用名稱縮寫.util 此包中包含:公共工具方法類(util模組名)
com.xx.應用名稱縮寫.bean 下面可分:vo、po、dto 此包中包含:JavaBean類
com.xx.應用名稱縮寫.model 此包中包含:模型類
com.xx.應用名稱縮寫.db 資料庫操作類
com.xx.應用名稱縮寫.view (或者 com.xx.應用名稱縮寫.widget ) 自定義的View類等
com.xx.應用名稱縮寫.service Service服務
com.xx.應用名稱縮寫.receiver BroadcastReceiver服務

注意:
如果專案採用MVP,所有M、V、P抽取出來的介面都放置在相應模組的i包下,所有的實現都放置在相應模組的impl下

5.2.2 類名

類名都以UpperCamelCase風格編寫。

類名通常是名詞或名詞短語,介面名稱有時可能是形容詞或形容詞短語。現在還沒有特定的規則或行之有效的約定來命名註解型別。

名詞,採用大駝峰命名法,儘量避免縮寫,除非該縮寫是眾所周知的, 比如HTML,URL,如果類名稱中包含單詞縮寫,則單詞縮寫的每個字母均應大寫。

描述 例如
Activity 類 Activity為字尾標識 歡迎頁面類WelcomeActivity
Adapter類 Adapter 為字尾標識 新聞詳情介面卡 NewDetailAdapter
解析類 Parser為字尾標識 首頁解析類HomePosterParser
工具方法類 Util或Manager為字尾標識(與系統或第三方的Utils區分)或功能+Util 執行緒池管理類:ThreadPoolManager日誌工具類:LogUtil(Logger也可)列印工具類:PrinterUtil
資料庫類 以DBHelper字尾標識 新聞資料庫:NewDBHelper
Service類 以Service為字尾標識 時間服務TimeServiceBroadcast
Receiver類 以Receiver為字尾標識 推送接收JPushReceiver
ContentProvider 以Provider為字尾標識
自定義的共享基礎類 以Base開頭 BaseActivity,BaseFragment

測試類的命名以它要測試的類的名稱開始,以Test結束。

例如:HashTest 或 HashIntegrationTest。

介面(interface):命名規則與類一樣採用大駝峰命名法,多以able或ible結尾,如

interface Runnable ;
interface Accessible。

注意:
如果專案採用MVP,所有Model、View、Presenter的介面都以I為字首,不加字尾,其他的介面採用上述命名規則。

5.2.3 方法名

方法名都以 LowerCamelCase 風格編寫。

方法名通常是動詞或動詞短語。

方法 說明
initXX() 初始化相關方法,使用init為字首標識,如初始化佈局initView()
isXX() checkXX() 方法返回值為boolean型的請使用is或check為字首標識
getXX() 返回某個值的方法,使用get為字首標識
handleXX() 對資料進行處理的方法,儘量使用handle為字首標識
displayXX()/showXX() 彈出提示框和提示資訊,使用display/show為字首標識
saveXX() 與儲存資料相關的,使用save為字首標識
resetXX() 對資料重組的,使用reset字首標識
clearXX() 清除資料相關的
removeXXX() 清除資料相關的
drawXXX() 繪製資料或效果相關的,使用draw字首標識

下劃線可能出現在JUnit測試方法名稱中用以分隔名稱的邏輯元件。一個典型的模式是:test_,例如testPop_emptyStack。

並不存在唯一正確的方式來命名測試方法。

5.2.4 常量名

常量名命名模式為CONSTANT_CASE,全部字母大寫,用下劃線分隔單詞。那,到底什麼算是一個常量?

每個常量都是一個靜態final欄位,但不是所有靜態final欄位都是常量。在決定一個欄位是否是一個常量時,考慮它是否真的感覺像是一個常量。

例如,如果任何一個該例項的觀測狀態是可變的,則它幾乎肯定不會是一個常量。只是永遠不打算改變物件一般是不夠的,它要真的一直不變才能將它示為常量。

// Constants
static final int NUMBER = 5;
static final ImmutableListNAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(','); // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }
// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final SetmutableCollection = new HashSet();
static final ImmutableSetmutableElements = ImmutableSet.of(mutable);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};

這些名字通常是名詞或名詞短語。

5.2.5 非常量欄位名

非常量欄位名以LowerCamelCase風格的基礎上改造為如下風格:

基本結構為scopeVariableNameType,

scope:範圍

非公有,非靜態欄位命名以m開頭。

靜態欄位命名以s開頭。

公有非靜態欄位命名以p開頭。

公有靜態欄位(全域性變數)命名以g開頭。

public static final 欄位(常量) 全部大寫,並用下劃線連起來。

例子:

public class MyClass {  
       public static final int SOME_CONSTANT = 42;  
       public int pField;  
       private static MyClass sSingleton;  
       int mPackagePrivate;  
       private int mPrivate;  
       protected int mProtected; 
       public static int gField; 
}

使用1字元字首來表示作用範圍,1個字元的字首必須小寫,字首後面是由表意性強的一個單詞或多個單片語成的名字,而且每個單詞的首寫字母大寫,其它字母小寫,這樣保證了對變數名能夠進行正確的斷句。

Type:型別

考慮到Android中使用很多UI控制元件,為避免控制元件和普通成員變數混淆以及更好達意,所有用來表示控制元件的成員變數統一加上控制元件縮寫作為字尾(文末附有縮寫表)。

對於普通變數一般不新增型別字尾,如果統一新增型別字尾,請參考文末的縮寫表。

用統一的量詞通過在結尾處放置一個量詞,就可建立更加統一的變數,它們更容易理解,也更容易搜尋。

注意:如果專案中使用ButterKnife,則不新增m字首,以LowerCamelCase風格命名。

例如,請使用 mCustomerStrFirst 和 mCustomerStrLast,而不要使用mFirstCustomerStr和mLastCustomerStr。

量詞列表:量詞字尾說明

First 一組變數中的第一個
Last 一組變數中的最後一個
Next 一組變數中的下一個變數
Prev 一組變數中的上一個
Cur 一組變數中的當前變數。

說明:

集合新增如下字尾:List、Map、Set

陣列新增如下字尾:Arr

注意:所有的VO(值物件)統一採用標準的lowerCamelCase風格編寫,所有的DTO(資料傳輸物件)就按照介面文件中定義的欄位名編寫。

5.2.6 引數名

引數名以LowerCamelCase風格編寫

5.2.7 區域性變數名

區域性變數名以LowerCamelCase風格編寫,比起其它型別的名稱,區域性變數名可以有更為寬鬆的縮寫。

雖然縮寫更寬鬆,但還是要避免用單字元進行命名,除了臨時變數和迴圈變數。

即使區域性變數是final和不可改變的,也不應該把它示為常量,自然也不能用常量的規則去命名它。

臨時變數

臨時變數通常被取名為i,j,k,m和n,它們一般用於整型;c,d,e,它們一般用於字元型。 如: for (int i = 0; i < len ; i++),並且它和第一個單詞間沒有空格。

5.2.8 型別變數名

型別變數可用以下兩種風格之一進行命名:

  • 單個的大寫字母,後面可以跟一個數字(如:E, T, X, T2)。
  • 以類命名方式(5.2.2節),後面加個大寫的T(如:RequestT, FooBarT)。

5.2.9 資原始檔命名規範

1. 資源佈局檔案(XML檔案(layout佈局檔案)):

全部小寫,採用下劃線命名法
1) contentview 命名
必須以全部單詞小寫,單詞間以下劃線分割,使用名詞或名詞片語。
所有Activity或Fragment的contentView必須與其類名對應,對應規則為:
將所有字母都轉為小寫,將型別和功能調換(也就是字尾變字首)。
例如:activity_main.xml

2) Dialog命名:dialog_描述.xml
例如:dialog_hint.xml

3) PopupWindow命名:ppw_描述.xml
例如:ppw_info.xml

4) 列表項命名:item_描述.xml
例如:item_city.xml

5) 包含項命名:模組_(位置)描述.xml
例如:activity_main_head.xmlactivity_main_bottom.xml
注意:通用的包含項命名採用:專案名稱縮寫_描述.xml
例如:xxxx_title.xml
2. 資原始檔(圖片drawable資料夾下):
全部小寫,採用下劃線命名法,加字首區分
命名模式:可加字尾 _small 表示小圖, _big 表示大圖,邏輯名稱可由多個單詞加下劃線組成,採用以下規則:
用途_模組名_邏輯名稱
用途_模組名_顏色
用途_邏輯名稱
用途_顏色
說明:用途也指控制元件型別(具體見UI控制元件縮寫表)
例如:
btn_main_home.png 按鍵
divider_maket_white.png 分割線
ic_edit.png 圖示
bg_main.png 背景
btn_red.png 紅色按鍵
btn_red_big.png 紅色大按鍵
ic_head_small.png 小頭像
bg_input.png 輸入框背景
divider_white.png 白色分割線
如果有多種形態如按鈕等除外如 btn_xx.xml(selector)

名稱 功能
btn_xx 按鈕圖片使用btn_整體效果(selector)
btn_xx_normal 按鈕圖片使用btn_正常情況效果
btn_xx_pressed 按鈕圖片使用btn_點選時候效果
btn_xx_focused state_focused聚焦效果
btn_xx_disabled state_enabled (false)不可用效果
btn_xx_checked state_checked選中效果
btn_xx_selected state_selected選中效果
btn_xx_hovered state_hovered懸停效果
btn_xx_checkable state_checkable可選效果
btn_xx_activated state_activated啟用的
btn_xx_windowfocused state_window_focused
bg_head 背景圖片使用bg_功能_說明
def_search_cell 預設圖片使用def_功能_說明
ic_more_help 圖示圖片使用ic_功能_說明
seg_list_line 具有分隔特徵的圖片使用seg_功能_說明
sel_ok 選擇圖示使用sel_功能_說明

注意:

使用AndroidStudio的外掛SelectorChapek可以快速生成selector,前提是命名要規範。

3. 動畫檔案(anim資料夾下):

全部小寫,採用下劃線命名法,加字首區分。
具體動畫採用以下規則:
模組名_邏輯名稱
邏輯名稱
refresh_progress.xml
market_cart_add.xml
market_cart_remove.xml
普通的tween動畫採用如下表格中的命名方式
// 前面為動畫的型別,後面為方向

動畫命名例子 規範寫法
fade_in 淡入
fade_out 淡出
push_down_in 從下方推入
push_down_out 從下方推出
push_left 推向左方
slide_in_from_top 從頭部滑動進入
zoom_enter 變形進入
slide_in 滑動進入
shrink_to_middle 中間縮小

4. values中name命名

類別 命名 示例
strings strings的name命名使用下劃線命名法,採用以下規則:模組名+邏輯名稱 main_menu_about 主選單按鍵文字friend_title 好友模組標題欄friend_dialog_del 好友刪除提示login_check_email 登入驗證

dialog_title 彈出框標題

button_ok 確認鍵 loading 載入文字

 

colors colors的name命名使用下劃線命名法,採用以下規則:模組名+邏輯名稱 顏色 friend_info_bg friend_bg transparent gray
styles styles的name命名使用 Camel命名法,採用以下規則:模組名+邏輯名稱 main_tabBottom

5. layout中的id命名

命名模式為:view縮寫_view的邏輯名稱
使用 AndroidStudio 的外掛 ButterKnife Zelezny,生成註解非常方便。
如果不使用 ButterKnife Zelezny,則建議使用 view 縮寫做字尾,如:username_tv(展示使用者名稱的TextView)

6. 程式設計實踐

6.1 @Override:能用則用

只要是合法的,就把@Override註解給用上。

6.2 捕獲的異常:不能忽視

除了下面的例子,對捕獲的異常不做響應是極少正確的。(典型的響應方式是列印日誌,或者如果它被認為是不可能的,則把它當作一個 AssertionError 重新丟擲。)

如果它確實是不需要在catch塊中做任何響應,需要做註釋加以說明(如下面的例子)。

try {
    int i = Integer.parseInt(response);
    return handleNumericResponse();
} catch (NumberFormatException ok) {
    // it's not numeric; that's fine, just continue
}
return handleTextResponse(response);

例外:在測試中,如果一個捕獲的異常被命名為expected,則它可以被不加註釋地忽略。下面是一種非常常見的情形,用以確保所測試的方法會丟擲一個期望中的異常,因此在這裡就沒有必要加註釋。

try {
    emptyStack.pop();
    fail();
} catch (NoSuchElementException expected) {
}

6.3 靜態成員:使用類進行呼叫

使用類名呼叫靜態的類成員,而不是具體某個物件或表示式。

Foo aFoo = ...;
Foo.aStaticMethod(); // good
aFoo.aStaticMethod(); // bad
somethingThatYieldsAFoo().aStaticMethod(); // very bad

6.4 Finalizers: 禁用

極少會去過載Object.finalize。

Tip:
不要使用finalize。如果你非要使用它,請先仔細閱讀和理解Effective Java 第7條款:”Avoid Finalizers”,然後不要使用它。

7. Javadoc

7.1 格式

7.1.1 一般形式

Javadoc塊的基本格式如下所示:

/**
* Multiple lines of Javadoc text are written here,
* wrapped normally...
*/
 public int method(String p1) { ... }

或者是以下單行形式:

/** An especially short bit of Javadoc. */

基本格式總是OK的。當整個Javadoc塊能容納於一行時(且沒有Javadoc標記@XXX),可以使用單行形式。

7.1.2 段落

空行(即,只包含最左側星號的行)會出現在段落之間和Javadoc標記(@XXX)之前(如果有的話)。

除了第一個段落,每個段落第一個單詞前都有標籤<p>,並且它和第一個單詞間沒有空格。

7.1.3 Javadoc標記

標準的Javadoc標記按以下順序出現:@param, @return, @throws, @deprecated,

前面這4種標記如果出現,描述都不能為空。 當描述無法在一行中容納,連續行需要至少再縮排4個空格。

7.2 摘要片段

每個類或成員的Javadoc以一個簡短的摘要片段開始。這個片段是非常重要的,在某些情況下,它是唯一出現的文字,比如在類和方法索引中。

這只是一個小片段,可以是一個名詞短語或動詞短語,但不是一個完整的句子。它不會以A {@code Foo} is a…或This method returns…開頭,它也不會是一個完整的祈使句,如Save the record…。然而,由於開頭大寫及被加了標點,它看起來就像是個完整的句子。

Tip:
一個常見的錯誤是把簡單的Javadoc寫成 /** @return the customer ID */,這是不正確的。它應該寫成/** Returns the customer ID. */

7.3 哪裡需要使用Javadoc

至少在每個public類及它的每個public和protected成員處使用Javadoc,以下是一些例外:

7.3.1 例外:不言自明的方法

對於簡單明顯的方法如getFoo,Javadoc是可選的(即,是可以不寫的)。這種情況下除了寫”Returns the foo”,確實也沒有什麼值得寫了。

單元測試類中的測試方法可能是不言自明的最常見例子了,我們通常可以從這些方法的描述性命名中知道它是幹什麼的,因此不需要額外的文件說明。

Tip:
如果有一些相關資訊是需要讀者瞭解的,那麼以上的例外不應作為忽視這些資訊的理由。例如,對於方法名getCanonicalName,

就不應該忽視文件說明,因為讀者很可能不知道詞語canonical name指的是什麼。

7.3.2 例外:過載

如果一個方法過載了超類中的方法,那麼Javadoc並非必需的。

7.3.3 可選的Javadoc

對於包外不可見的類和方法,如有需要,也是要使用Javadoc的。如果一個註釋是用來定義一個類,方法,欄位的整體目的或行為,那麼這個註釋應該寫成Javadoc,這樣更統一更友好。

附錄:

表1 UI控制元件縮寫表

控制元件 縮寫 例子
LinearLayout ll llFriend或者mFriendLL
RelativeLayout rl rlMessage或mMessageRL
FrameLayout fl flCart或mCartFL
TableLayout tl tlTab或mTabTL
Button btn btnHome或mHomeBtn
ImageButton ibtn btnPlay或mPlayIBtn
TextView tv tvName或mNameTV
EditText et etName或mNameET
ListView lv lvCart或mCartLV
ImageView iv ivHead或mHeadIV
GridView gv gvPhoto或mPhotoGV

表2 常見的英文單詞縮寫:

名稱 縮寫
icon ic (主要用在app的圖示)
color cl(主要用於顏色值)
divider di(主要用於分隔線,不僅包括Listview中的divider,還包括普通佈局中的線)
selector sl(主要用於某一view多種狀態,不僅包括Listview中的selector,還包括按鈕的selector)
average avg
background bg(主要用於佈局和子佈局的背景)
buffer buf
control ctrl
delete del
document doc
error err
escape esc
increment inc
infomation info
initial init
image img
Internationalization I18N
length len
library lib
message msg
password pwd
position pos
server srv
string str
temp tmp
window wnd(win)

程式中使用單詞縮寫原則:不要用縮寫,除非該縮寫是約定俗成的。

相關文章