Android 開發(fā)規(guī)范(轉(zhuǎn)載 Blankj 作品)

摘要

1 前言

為了有利于項(xiàng)目維護(hù)饲梭、增強(qiáng)代碼可讀性、提升 Code Review 效率以及規(guī)范團(tuán)隊(duì)安卓開發(fā),故提出以下安卓開發(fā)規(guī)范境肾,該規(guī)范結(jié)合本人多年的開發(fā)經(jīng)驗(yàn)并吸取多家之精華闽巩,可謂是本人的嘔心瀝血之作糯俗,稱其為當(dāng)前最完善的安卓開發(fā)規(guī)范一點(diǎn)也不為過饶唤,如有更好建議蓝翰,歡迎到 GitHub 提 issue光绕,原文地址:[Android 開發(fā)規(guī)范(完結(jié)版)][Android 開發(fā)規(guī)范(完結(jié)版)]。相關(guān) Demo畜份,可以查看我的 Android 開發(fā)工具類集合項(xiàng)目:[Android 開發(fā)人員不得不收集的代碼][Android 開發(fā)人員不得不收集的代碼]诞帐。后續(xù)可能會(huì)根據(jù)該規(guī)范出一個(gè) CheckStyle 插件來檢查是否規(guī)范,當(dāng)然也支持在 CI 上運(yùn)行爆雹。

2 AS 規(guī)范

工欲善其事停蕉,必先利其器。

  1. 盡量使用最新的穩(wěn)定版的 IDE 進(jìn)行開發(fā)钙态;
  2. 編碼格式統(tǒng)一為 UTF-8慧起;
  3. 編輯完 .java、.xml 等文件后一定要 格式化册倒,格式化蚓挤,格式化(如果團(tuán)隊(duì)有公共的樣式包,那就遵循它,否則統(tǒng)一使用 AS 默認(rèn)模板即可)灿意;
  4. 刪除多余的 import估灿,減少警告出現(xiàn),可利用 AS 的 Optimize Imports(Settings -> Keymap -> Optimize Imports)快捷鍵脾歧;
  5. Android 開發(fā)者工具可以參考這里:[Android 開發(fā)者工具][Android 開發(fā)者工具]甲捏;

3 命名規(guī)范

代碼中的命名嚴(yán)禁使用拼音與英文混合的方式演熟,更不允許直接使用中文的方式鞭执。正確的英文拼寫和語法可以讓閱讀者易于理解,避免歧義芒粹。

注意:即使純拼音命名方式也要避免采用兄纺。但 alibabataobao化漆、youku估脆、hangzhou 等國際通用的名稱,可視同英文座云。

3.1 包名

包名全部小寫疙赠,連續(xù)的單詞只是簡(jiǎn)單地連接起來,不使用下劃線朦拖,采用反域名命名規(guī)則圃阳,全部使用小寫字母。一級(jí)包名是頂級(jí)域名璧帝,通常為 com捍岳、edugov睬隶、net锣夹、org 等,二級(jí)包名為公司名苏潜,三級(jí)包名根據(jù)應(yīng)用進(jìn)行命名银萍,后面就是對(duì)包名的劃分了,關(guān)于包名的劃分恤左,推薦采用 PBF(按功能分包 Package By Feature)砖顷,一開始我們采用的也是 PBL(按層分包 Package By Layer),很坑爹赃梧。PBF 可能不是很好區(qū)分在哪個(gè)功能中滤蝠,不過也比 PBL 要好找很多,且 PBF 與 PBL 相比較有如下優(yōu)勢(shì):

  • package 內(nèi)高內(nèi)聚授嘀,package 間低耦合

    哪塊要添新功能物咳,只改某一個(gè) package 下的東西。

    PBL 降低了代碼耦合蹄皱,但帶來了 package 耦合览闰,要添新功能芯肤,需要改 model、dbHelper压鉴、view崖咨、service 等等,需要改動(dòng)好幾個(gè) package 下的代碼油吭,改動(dòng)的地方越多击蹲,越容易產(chǎn)生新問題,不是嗎婉宰?

    PBF 的話 featureA 相關(guān)的所有東西都在 featureA 包歌豺,feature 內(nèi)高內(nèi)聚、高度模塊化心包,不同 feature 之間低耦合类咧,相關(guān)的東西都放在一起,還好找蟹腾。

  • package 有私有作用域(package-private scope)

    你負(fù)責(zé)開發(fā)這塊功能痕惋,這個(gè)目錄下所有東西都是你的。

    PBL 的方式是把所有工具方法都放在 util 包下娃殖,小張開發(fā)新功能時(shí)候發(fā)現(xiàn)需要一個(gè) xxUtil值戳,但它又不是通用的,那應(yīng)該放在哪里珊随?沒辦法述寡,按照分層原則,我們還得放在 util 包下叶洞,好像不太合適鲫凶,但放在其它包更不合適,功能越來越多衩辟,util 類也越定義越多螟炫。后來小李負(fù)責(zé)開發(fā)一塊功能時(shí)發(fā)現(xiàn)需要一個(gè) xxUtil,同樣不通用艺晴,去 util 包一看昼钻,怎么已經(jīng)有了,而且還沒法復(fù)用封寞,只好放棄 xx 這個(gè)名字然评,改為 xxxUtil……,因?yàn)?PBL 的 package 沒有私有作用域狈究,每一個(gè)包都是 public(跨包方法調(diào)用是很平常的事情碗淌,每一個(gè)包對(duì)其它包來說都是可訪問的);如果是 PBF,小張的 xxUtil 自然放在 featureA 下亿眠,小李的 xxUtil 在 featureB 下碎罚,如果覺得 util 好像是通用的,就去 util 包看看要不要把工具方法添進(jìn) xxUtil, class 命名沖突沒有了纳像。

    PBF 的 package 有私有作用域荆烈,featureA 不應(yīng)該訪問 featureB 下的任何東西(如果非訪問不可,那就說明接口定義有問題)竟趾。

  • 很容易刪除功能

    統(tǒng)計(jì)發(fā)現(xiàn)新功能沒人用憔购,這個(gè)版本那塊功能得去掉。

    如果是 PBL潭兽,得從功能入口到整個(gè)業(yè)務(wù)流程把受到牽連的所有能刪的代碼和 class 都揪出來刪掉倦始,一不小心就完蛋斗遏。

    如果是 PBF山卦,好說,先刪掉對(duì)應(yīng)包诵次,再刪掉功能入口(刪掉包后入口肯定報(bào)錯(cuò)了)账蓉,完事。

  • 高度抽象

    解決問題的一般方法是從抽象到具體逾一,PBF 包名是對(duì)功能模塊的抽象铸本,包內(nèi)的 class 是實(shí)現(xiàn)細(xì)節(jié),符合從抽象到具體遵堵,而 PBL 弄反了箱玷。

    PBF 從確定 AppName 開始,根據(jù)功能模塊劃分 package陌宿,再考慮每塊的具體實(shí)現(xiàn)細(xì)節(jié)锡足,而 PBL 從一開始就要考慮要不要 dao 層,要不要 com 層等等壳坪。

  • 只通過 class 來分離邏輯代碼

    PBL 既分離 class 又分離 package舶得,而 PBF 只通過 class 來分離邏輯代碼。

    沒有必要通過 package 分離爽蝴,因?yàn)?PBL 中也可能出現(xiàn)尷尬的情況:

    ├── service
            ├── MainService.java
    

    按照 PBL, service 包下的所有東西都是 Service沐批,應(yīng)該不需要 Service 后綴,但實(shí)際上通常為了方便蝎亚,直接 import service 包九孩,Service 后綴是為了避免引入的 class 和當(dāng)前包下的 class 命名沖突,當(dāng)然发框,不用后綴也可以躺彬,得寫清楚包路徑,比如 new com.domain.service.MainService(),麻煩顾患;而 PBF 就很方便番捂,無需 import,直接 new MainService() 即可江解。

  • package 的大小有意義了

    PBL 中包的大小無限增長(zhǎng)是合理的设预,因?yàn)楣δ茉教碓蕉啵?PBF 中包太大(包里 class 太多)表示這塊需要重構(gòu)(劃分子包)犁河。

如要知道更多好處鳖枕,可以查看這篇博文:[Package by features, not layers][Package by features, not layers],當(dāng)然桨螺,我們大谷歌也有相應(yīng)的 Sample:[todo-mvp][todo-mvp]宾符,其結(jié)構(gòu)如下所示,很值得學(xué)習(xí)灭翔。

com
└── example
    └── android
        └── architecture
            └── blueprints
                └── todoapp
                    ├── BasePresenter.java
                    ├── BaseView.java
                    ├── addedittask
                    │   ├── AddEditTaskActivity.java
                    │   ├── AddEditTaskContract.java
                    │   ├── AddEditTaskFragment.java
                    │   └── AddEditTaskPresenter.java
                    ├── data
                    │   ├── Task.java
                    │   └── source
                    │       ├── TasksDataSource.java
                    │       ├── TasksRepository.java
                    │       ├── local
                    │       │   ├── TasksDbHelper.java
                    │       │   ├── TasksLocalDataSource.java
                    │       │   └── TasksPersistenceContract.java
                    │       └── remote
                    │           └── TasksRemoteDataSource.java
                    ├── statistics
                    │   ├── StatisticsActivity.java
                    │   ├── StatisticsContract.java
                    │   ├── StatisticsFragment.java
                    │   └── StatisticsPresenter.java
                    ├── taskdetail
                    │   ├── TaskDetailActivity.java
                    │   ├── TaskDetailContract.java
                    │   ├── TaskDetailFragment.java
                    │   └── TaskDetailPresenter.java
                    ├── tasks
                    │   ├── ScrollChildSwipeRefreshLayout.java
                    │   ├── TasksActivity.java
                    │   ├── TasksContract.java
                    │   ├── TasksFilterType.java
                    │   ├── TasksFragment.java
                    │   └── TasksPresenter.java
                    └── util
                        ├── ActivityUtils.java
                        ├── EspressoIdlingResource.java
                        └── SimpleCountingIdlingResource.java

參考以上的代碼結(jié)構(gòu)魏烫,按功能分包具體可以這樣做:

com
└── domain
    └── app
        ├── App.java 定義 Application 類
        ├── Config.java 定義配置數(shù)據(jù)(常量)
        ├── base 基礎(chǔ)組件
        ├── custom_view 自定義視圖
        ├── data 數(shù)據(jù)處理
        │   ├── DataManager.java 數(shù)據(jù)管理器,
        │   ├── local 來源于本地的數(shù)據(jù)肝箱,比如 SP哄褒,Database,F(xiàn)ile
        │   ├── model 定義 model(數(shù)據(jù)結(jié)構(gòu)以及 getter/setter煌张、compareTo呐赡、equals 等等,不含復(fù)雜操作)
        │   └── remote 來源于遠(yuǎn)端的數(shù)據(jù)
        ├── feature 功能
        │   ├── feature0 功能 0
        │   │   ├── feature0Activity.java
        │   │   ├── feature0Fragment.java
        │   │   ├── xxAdapter.java
        │   │   └── ... 其他 class
        │   └── ...其他功能
        ├── injection 依賴注入
        ├── util 工具類
        └── widget 小部件

3.2 類名

類名都以 UpperCamelCase 風(fēng)格編寫骏融。

類名通常是名詞或名詞短語链嘀,接口名稱有時(shí)可能是形容詞或形容詞短語。現(xiàn)在還沒有特定的規(guī)則或行之有效的約定來命名注解類型档玻。

名詞怀泊,采用大駝峰命名法,盡量避免縮寫窃肠,除非該縮寫是眾所周知的包个, 比如 HTML、URL冤留,如果類名稱中包含單詞縮寫碧囊,則單詞縮寫的每個(gè)字母均應(yīng)大寫。

描述 例如
Activity Activity 為后綴標(biāo)識(shí) 歡迎頁面類 WelcomeActivity
Adapter Adapter 為后綴標(biāo)識(shí) 新聞詳情適配器 NewsDetailAdapter
解析類 Parser 為后綴標(biāo)識(shí) 首頁解析類 HomePosterParser
工具方法類 UtilsManager 為后綴標(biāo)識(shí) 線程池管理類:ThreadPoolManager
日志工具類:LogUtilsLogger 也可)
打印工具類:PrinterUtils
數(shù)據(jù)庫類 DBHelper 后綴標(biāo)識(shí) 新聞數(shù)據(jù)庫:NewsDBHelper
Service Service 為后綴標(biāo)識(shí) 時(shí)間服務(wù) TimeService
BroadcastReceiver Receiver 為后綴標(biāo)識(shí) 推送接收 JPushReceiver
ContentProvider Provider 為后綴標(biāo)識(shí) ShareProvider
自定義的共享基礎(chǔ)類 Base 開頭 BaseActivity, BaseFragment

測(cè)試類的命名以它要測(cè)試的類的名稱開始纤怒,以 Test 結(jié)束糯而。例如:HashTestHashIntegrationTest

接口(interface):命名規(guī)則與類一樣采用大駝峰命名法泊窘,多以 able 或 ible 結(jié)尾熄驼,如 interface Runnable像寒、interface Accessible

注意:如果項(xiàng)目采用 MVP瓜贾,所有 Model诺祸、View、Presenter 的接口都以 I 為前綴祭芦,不加后綴筷笨,其他的接口采用上述命名規(guī)則。

3.3 方法名

方法名都以 lowerCamelCase 風(fēng)格編寫龟劲。

方法名通常是動(dòng)詞或動(dòng)詞短語胃夏。

方法 說明
initXX() 初始化相關(guān)方法,使用 init 為前綴標(biāo)識(shí)昌跌,如初始化布局 initView()
isXX(), checkXX() 方法返回值為 boolean 型的請(qǐng)使用 is/check 為前綴標(biāo)識(shí)
getXX() 返回某個(gè)值的方法仰禀,使用 get 為前綴標(biāo)識(shí)
setXX() 設(shè)置某個(gè)屬性值
handleXX(), processXX() 對(duì)數(shù)據(jù)進(jìn)行處理的方法
displayXX(), showXX() 彈出提示框和提示信息,使用 display/show 為前綴標(biāo)識(shí)
updateXX() 更新數(shù)據(jù)
saveXX(), insertXX() 保存或插入數(shù)據(jù)
resetXX() 重置數(shù)據(jù)
clearXX() 清除數(shù)據(jù)
removeXX(), deleteXX() 移除數(shù)據(jù)或者視圖等蚕愤,如 removeView()
drawXX() 繪制數(shù)據(jù)或效果相關(guān)的答恶,使用 draw 前綴標(biāo)識(shí)

3.4 常量名

常量名命名模式為 CONSTANT_CASE,全部字母大寫审胸,用下劃線分隔單詞亥宿。那到底什么算是一個(gè)常量卸勺?

每個(gè)常量都是一個(gè) static final 字段砂沛,但不是所有 static final 字段都是常量。在決定一個(gè)字段是否是一個(gè)常量時(shí)曙求,得考慮它是否真的感覺像是一個(gè)常量碍庵。例如,如果觀測(cè)任何一個(gè)該實(shí)例的狀態(tài)是可變的悟狱,則它幾乎肯定不會(huì)是一個(gè)常量静浴。只是永遠(yuǎn)不打算改變的對(duì)象一般是不夠的,它要真的一直不變才能將它示為常量挤渐。

// 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"};

3.5 非常量字段名

非常量字段名以 lowerCamelCase 風(fēng)格的基礎(chǔ)上改造為如下風(fēng)格:基本結(jié)構(gòu)為 scope{Type0}VariableName{Type1}苹享、type0VariableName{Type1}variableName{Type1}浴麻。

說明:{} 中的內(nèi)容為可選得问。

注意:所有的 VO(值對(duì)象)統(tǒng)一采用標(biāo)準(zhǔn)的 lowerCamelCase 風(fēng)格編寫,所有的 DTO(數(shù)據(jù)傳輸對(duì)象)就按照接口文檔中定義的字段名編寫软免。

3.5.1 scope(范圍)

非公有宫纬,非靜態(tài)字段命名以 m 開頭。

靜態(tài)字段命名以 s 開頭膏萧。

其他字段以小寫字母開頭漓骚。

例如:

public class MyClass {
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}

使用 1 個(gè)字符前綴來表示作用范圍蝌衔,1 個(gè)字符的前綴必須小寫,前綴后面是由表意性強(qiáng)的一個(gè)單詞或多個(gè)單詞組成的名字蝌蹂,而且每個(gè)單詞的首寫字母大寫噩斟,其它字母小寫,這樣保證了對(duì)變量名能夠進(jìn)行正確的斷句孤个。

3.5.2 Type0(控件類型)

考慮到 Android 眾多的 UI 控件亩冬,為避免控件和普通成員變量混淆以及更好地表達(dá)意思,所有用來表示控件的成員變量統(tǒng)一加上控件縮寫作為前綴(具體見附錄 UI 控件縮寫表)硼身。

例如:mIvAvatar硅急、rvBooksflContainer佳遂。

3.5.3 VariableName(變量名)

變量名中可能會(huì)出現(xiàn)量詞营袜,我們需要?jiǎng)?chuàng)建統(tǒng)一的量詞,它們更容易理解丑罪,也更容易搜索荚板。

例如:mFirstBookmPreBook吩屹、curBook跪另。

量詞列表 量詞后綴說明
First 一組變量中的第一個(gè)
Last 一組變量中的最后一個(gè)
Next 一組變量中的下一個(gè)
Pre 一組變量中的上一個(gè)
Cur 一組變量中的當(dāng)前變量
3.5.4 Type1(數(shù)據(jù)類型)

對(duì)于表示集合或者數(shù)組的非常量字段名,我們可以添加后綴來增強(qiáng)字段的可讀性煤搜,比如:

集合添加如下后綴:List免绿、Map、Set擦盾。

數(shù)組添加如下后綴:Arr嘲驾。

例如:mIvAvatarListuserArr迹卢、firstNameSet辽故。

注意:如果數(shù)據(jù)類型不確定的話,比如表示的是很多書腐碱,那么使用其復(fù)數(shù)形式來表示也可誊垢,例如 mBooks

3.6 參數(shù)名

參數(shù)名以 lowerCamelCase 風(fēng)格編寫症见,參數(shù)應(yīng)該避免用單個(gè)字符命名喂走。

3.7 局部變量名

局部變量名以 lowerCamelCase 風(fēng)格編寫,比起其它類型的名稱筒饰,局部變量名可以有更為寬松的縮寫缴啡。

雖然縮寫更寬松,但還是要避免用單字符進(jìn)行命名瓷们,除了臨時(shí)變量和循環(huán)變量业栅。

即使局部變量是 final 和不可改變的秒咐,也不應(yīng)該把它示為常量,自然也不能用常量的規(guī)則去命名它碘裕。

3.8 臨時(shí)變量

臨時(shí)變量通常被取名為 i携取、jk帮孔、mn雷滋,它們一般用于整型;c文兢、d晤斩、e,它們一般用于字符型姆坚。 如:for (int i = 0; i < len; i++)澳泵。

3.9 類型變量名

類型變量可用以下兩種風(fēng)格之一進(jìn)行命名:

  1. 單個(gè)的大寫字母,后面可以跟一個(gè)數(shù)字(如:E, T, X, T2)兼呵。
  2. 以類命名方式(參考3.2 類名)兔辅,后面加個(gè)大寫的 T(如:RequestT, FooBarT)。

更多還可參考:[阿里巴巴 Java 開發(fā)手冊(cè)][阿里巴巴 Java 開發(fā)手冊(cè)]

4 代碼樣式規(guī)范

4.1 使用標(biāo)準(zhǔn)大括號(hào)樣式

左大括號(hào)不單獨(dú)占一行击喂,與其前面的代碼位于同一行:

class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

我們需要在條件語句周圍添加大括號(hào)维苔。例外情況:如果整個(gè)條件語句(條件和主體)適合放在同一行,那么您可以(但不是必須)將其全部放在一行上懂昂。例如介时,我們接受以下樣式:

if (condition) {
    body();
}

同樣也接受以下樣式:

if (condition) body();

但不接受以下樣式:

if (condition)
    body();  // bad!

4.2 編寫簡(jiǎn)短方法

在可行的情況下,盡量編寫短小精煉的方法忍法。我們了解潮尝,有些情況下較長(zhǎng)的方法是恰當(dāng)?shù)模虼藢?duì)方法的代碼長(zhǎng)度沒有做出硬性限制饿序。如果某個(gè)方法的代碼超出 40 行,請(qǐng)考慮是否可以在不破壞程序結(jié)構(gòu)的前提下對(duì)其拆解羹蚣。

4.3 類成員的順序

這并沒有唯一的正確解決方案原探,但如果都使用一致的順序?qū)?huì)提高代碼的可讀性,推薦使用如下排序:

  1. 常量
  2. 字段
  3. 構(gòu)造函數(shù)
  4. 重寫函數(shù)和回調(diào)
  5. 公有函數(shù)
  6. 私有函數(shù)
  7. 內(nèi)部類或接口

例如:

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    private String mTitle;
    private TextView mTextViewTitle;

    @Override
    public void onCreate() {
        ...
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    private void setUpView() {
        ...
    }

    static class AnInnerClass {

    }
}

如果類繼承于 Android 組件(例如 ActivityFragment)顽素,那么把重寫函數(shù)按照他們的生命周期進(jìn)行排序是一個(gè)非常好的習(xí)慣咽弦,例如,Activity 實(shí)現(xiàn)了 onCreate()胁出、onDestroy()型型、onPause()onResume()全蝶,它的正確排序如下所示:

public class MainActivity extends Activity {
    //Order matches Activity lifecycle
    @Override
    public void onCreate() {}

    @Override
    public void onResume() {}

    @Override
    public void onPause() {}

    @Override
    public void onDestroy() {}
}

4.4 函數(shù)參數(shù)的排序

在 Android 開發(fā)過程中闹蒜,Context 在函數(shù)參數(shù)中是再常見不過的了寺枉,我們最好把 Context 作為其第一個(gè)參數(shù)。

正相反绷落,我們把回調(diào)接口應(yīng)該作為其最后一個(gè)參數(shù)姥闪。

例如:

// Context always goes first
public User loadUser(Context context, int userId);

// Callbacks always go last
public void loadUserAsync(Context context, int userId, UserCallback callback);

4.5 字符串常量的命名和值

Android SDK 中的很多類都用到了鍵值對(duì)函數(shù),比如 SharedPreferences砌烁、Bundle筐喳、Intent,所以函喉,即便是一個(gè)小應(yīng)用避归,我們最終也不得不編寫大量的字符串常量。

當(dāng)時(shí)用到這些類的時(shí)候管呵,我們 必須 將它們的鍵定義為 static final 字段槐脏,并遵循以下指示作為前綴。

字段名前綴
SharedPreferences PREF_
Bundle BUNDLE_
Fragment Arguments ARGUMENT_
Intent Extra EXTRA_
Intent Action ACTION_

說明:雖然 Fragment.getArguments() 得到的也是 Bundle 撇寞,但因?yàn)檫@是 Bundle 的常用用法顿天,所以特意為此定義一個(gè)不同的前綴。

例如:

// 注意:字段的值與名稱相同以避免重復(fù)問題
static final String PREF_EMAIL = "PREF_EMAIL";
static final String BUNDLE_AGE = "BUNDLE_AGE";
static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID";

// 與意圖相關(guān)的項(xiàng)使用完整的包名作為值的前綴
static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME";
static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER";

4.6 Activities 和 Fragments 的傳參

當(dāng) ActivityFragment 傳遞數(shù)據(jù)通過 IntentBundle 時(shí)蔑担,不同值的鍵須遵循上一條所提及到的牌废。

當(dāng) ActivityFragment 啟動(dòng)需要傳遞參數(shù)時(shí),那么它需要提供一個(gè) public static 的函數(shù)來幫助啟動(dòng)或創(chuàng)建它啤握。

這方面鸟缕,AS 已幫你寫好了相關(guān)的 Live Templates,啟動(dòng)相關(guān) Activity 的只需要在其內(nèi)部輸入 starter 即可生成它的啟動(dòng)器排抬,如下所示:

public static void start(Context context, User user) {
      Intent starter = new Intent(context, MainActivity.class);
      starter.putParcelableExtra(EXTRA_USER, user);
      context.startActivity(starter);
}

同理懂从,啟動(dòng)相關(guān) Fragment 在其內(nèi)部輸入 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;
}

注意:這些函數(shù)需要放在 onCreate() 之前的類的頂部蹲蒲;如果我們使用了這種方式番甩,那么 extrasarguments 的鍵應(yīng)該是 private 的,因?yàn)樗鼈儾辉傩枰┞督o其他類來使用届搁。

4.7 行長(zhǎng)限制

代碼中每一行文本的長(zhǎng)度都應(yīng)該不超過 100 個(gè)字符缘薛。雖然關(guān)于此規(guī)則存在很多爭(zhēng)論,但最終決定仍是以 100 個(gè)字符為上限卡睦,如果行長(zhǎng)超過了 100(AS 窗口右側(cè)的豎線就是設(shè)置的行寬末尾 )宴胧,我們通常有兩種方法來縮減行長(zhǎng)。

  • 提取一個(gè)局部變量或方法(最好)表锻。
  • 使用換行符將一行換成多行恕齐。

不過存在以下例外情況:

  • 如果備注行包含長(zhǎng)度超過 100 個(gè)字符的示例命令或文字網(wǎng)址,那么為了便于剪切和粘貼瞬逊,該行可以超過 100 個(gè)字符显歧。
  • 導(dǎo)入語句行可以超出此限制仪或,因?yàn)橛脩艉苌贂?huì)看到它們(這也簡(jiǎn)化了工具編寫流程)。
4.7.1 換行策略

這沒有一個(gè)準(zhǔn)確的解決方案來決定如何換行追迟,通常不同的解決方案都是有效的溶其,但是有一些規(guī)則可以應(yīng)用于常見的情況。

4.7.1.1 操作符的換行

除賦值操作符之外敦间,我們把換行符放在操作符之前瓶逃,例如:

int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne
        + theFinalOne;

賦值操作符的換行我們放在其后,例如:

int longName =
        anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne;
4.7.1.2 函數(shù)鏈的換行

當(dāng)同一行中調(diào)用多個(gè)函數(shù)時(shí)(比如使用構(gòu)建器時(shí))廓块,對(duì)每個(gè)函數(shù)的調(diào)用應(yīng)該在新的一行中厢绝,我們把換行符插入在 . 之前。

例如:

Picasso.with(context).load("https://blankj.com/images/avatar.jpg").into(ivAvatar);

我們應(yīng)該使用如下規(guī)則:

Picasso.with(context)
        .load("https://blankj.com/images/avatar.jpg")
        .into(ivAvatar);
4.7.1.3 多參數(shù)的換行

當(dāng)一個(gè)方法有很多參數(shù)或者參數(shù)很長(zhǎng)的時(shí)候带猴,我們應(yīng)該在每個(gè) , 后面進(jìn)行換行昔汉。

比如:

loadPicture(context, "https://blankj.com/images/avatar.jpg", ivAvatar, "Avatar of the user", clickListener);

我們應(yīng)該使用如下規(guī)則:

loadPicture(context,
        "https://blankj.com/images/avatar.jpg",
        ivAvatar,
        "Avatar of the user",
        clickListener);
4.7.1.4 RxJava 鏈?zhǔn)降膿Q行

RxJava 的每個(gè)操作符都需要換新行,并且把換行符插入在 . 之前拴清。

例如:

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;
                 }
            });
}

5 資源文件規(guī)范

資源文件命名為全部小寫靶病,采用下劃線命名法。

如果是組件化開發(fā)口予,我們可以在組件和公共模塊間創(chuàng)建一個(gè) ui 模塊來專門存放資源文件娄周,然后讓每個(gè)組件都依賴 ui 模塊。這樣做的好處是如果老項(xiàng)目要實(shí)現(xiàn)組件化的話沪停,只需把資源文件都放入 ui 模塊即可煤辨,如果想對(duì)資源文件進(jìn)行分包,可以參考我這篇文章:[Android Studio 下對(duì)資源進(jìn)行分包][Android Studio 下對(duì)資源進(jìn)行分包]木张;還避免了多個(gè)模塊間資源不能復(fù)用的問題众辨。

如果是三方庫開發(fā),其使用到的資源文件及相關(guān)的 name 都應(yīng)該使用庫名作為前綴舷礼,這樣做可以避免三方庫資源和實(shí)際應(yīng)用資源重名的沖突鹃彻。

5.1 動(dòng)畫資源文件(anim/ 和 animator/)

安卓主要包含屬性動(dòng)畫和視圖動(dòng)畫,其視圖動(dòng)畫包括補(bǔ)間動(dòng)畫和逐幀動(dòng)畫且轨。屬性動(dòng)畫文件需要放在 res/animator/ 目錄下浮声,視圖動(dòng)畫文件需放在 res/anim/ 目錄下。

命名規(guī)則:{模塊名_}邏輯名稱旋奢。

說明:{} 中的內(nèi)容為可選,邏輯名稱 可由多個(gè)單詞加下劃線組成然痊。

例如:refresh_progress.xml至朗、market_cart_add.xmlmarket_cart_remove.xml剧浸。

如果是普通的補(bǔ)間動(dòng)畫或者屬性動(dòng)畫锹引,可采用:動(dòng)畫類型_方向 的命名方式矗钟。

例如:

名稱 說明
fade_in 淡入
fade_out 淡出
push_down_in 從下方推入
push_down_out 從下方推出
push_left 推向左方
slide_in_from_top 從頭部滑動(dòng)進(jìn)入
zoom_enter 變形進(jìn)入
slide_in 滑動(dòng)進(jìn)入
shrink_to_middle 中間縮小

5.2 顏色資源文件(color/)

專門存放顏色相關(guān)的資源文件。

命名規(guī)則:類型{_模塊名}_邏輯名稱嫌变。

說明:{} 中的內(nèi)容為可選吨艇。

例如:sel_btn_font.xml

顏色資源也可以放于 res/drawable/ 目錄腾啥,引用時(shí)則用 @drawable 來引用东涡,但不推薦這么做,最好還是把兩者分開倘待。

5.3 圖片資源文件(drawable/ 和 mipmap/)

res/drawable/ 目錄下放的是位圖文件(.png疮跑、.9.png、.jpg凸舵、.gif)或編譯為可繪制對(duì)象資源子類型的 XML 文件祖娘,而 res/mipmap/ 目錄下放的是不同密度的啟動(dòng)圖標(biāo),所以 res/mipmap/ 只用于存放啟動(dòng)圖標(biāo)啊奄,其余圖片資源文件都應(yīng)該放到 res/drawable/ 目錄下渐苏。

命名規(guī)則:類型{_模塊名}_邏輯名稱類型{_模塊名}_顏色菇夸。

說明:{} 中的內(nèi)容為可選琼富;類型 可以是可繪制對(duì)象資源類型,也可以是控件類型(具體見附錄UI 控件縮寫表)峻仇;最后可加后綴 _small 表示小圖公黑,_big 表示大圖。

例如:

名稱 說明
btn_main_about.png 主頁關(guān)于按鍵 類型_模塊名_邏輯名稱
btn_back.png 返回按鍵 類型_邏輯名稱
divider_maket_white.png 商城白色分割線 類型_模塊名_顏色
ic_edit.png 編輯圖標(biāo) 類型_邏輯名稱
bg_main.png 主頁背景 類型_邏輯名稱
btn_red.png 紅色按鍵 類型_顏色
btn_red_big.png 紅色大按鍵 類型_顏色
ic_head_small.png 小頭像圖標(biāo) 類型_邏輯名稱
bg_input.png 輸入框背景 類型_邏輯名稱
divider_white.png 白色分割線 類型_顏色
bg_main_head.png 主頁頭部背景 類型_模塊名_邏輯名稱
def_search_cell.png 搜索頁面默認(rèn)單元圖片 類型_模塊名_邏輯名稱
ic_more_help.png 更多幫助圖標(biāo) 類型_邏輯名稱
divider_list_line.png 列表分割線 類型_邏輯名稱
sel_search_ok.xml 搜索界面確認(rèn)選擇器 類型_模塊名_邏輯名稱
shape_music_ring.xml 音樂界面環(huán)形形狀 類型_模塊名_邏輯名稱

如果有多種形態(tài)摄咆,如按鈕選擇器:sel_btn_xx.xml凡蚜,采用如下命名:

名稱 說明
sel_btn_xx 作用在 btn_xx 上的 selector
btn_xx_normal 默認(rèn)狀態(tài)效果
btn_xx_pressed state_pressed 點(diǎn)擊效果
btn_xx_focused state_focused 聚焦效果
btn_xx_disabled state_enabled 不可用效果
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_window_focused state_window_focused 窗口聚焦效果

注意:使用 Android Studio 的插件 SelectorChapek 可以快速生成 selector为障,前提是命名要規(guī)范涮瞻。

5.4 布局資源文件(layout/)

命名規(guī)則:類型_模塊名類型{_模塊名}_邏輯名稱臣咖。

說明:{} 中的內(nèi)容為可選涩金。

例如:

名稱 說明
activity_main.xml 主窗體 類型_模塊名
activity_main_head.xml 主窗體頭部 類型_模塊名_邏輯名稱
fragment_music.xml 音樂片段 類型_模塊名
fragment_music_player.xml 音樂片段的播放器 類型_模塊名_邏輯名稱
dialog_loading.xml 加載對(duì)話框 類型_邏輯名稱
ppw_info.xml 信息彈窗(PopupWindow) 類型_邏輯名稱
item_main_song.xml 主頁歌曲列表項(xiàng) 類型_模塊名_邏輯名稱

5.5 菜單資源文件(menu/)

菜單相關(guān)的資源文件應(yīng)放在該目錄下谱醇。

命名規(guī)則:{模塊名_}邏輯名稱

說明:{} 中的內(nèi)容為可選。

例如:main_drawer.xml步做、navigation.xml副渴。

5.6 values 資源文件(values/)

values/ 資源文件下的文件都以 s 結(jié)尾,如 attrs.xml全度、colors.xml煮剧、dimens.xml,起作用的不是文件名稱,而是 <resources> 標(biāo)簽下的各種標(biāo)簽勉盅,比如 <style> 決定樣式佑颇,<color> 決定顏色,所以草娜,可以把一個(gè)大的 xml 文件分割成多個(gè)小的文件挑胸,比如可以有多個(gè) style 文件,如 styles.xml宰闰、styles_home.xml茬贵、styles_item_details.xmlstyles_forms.xml议蟆。

5.6.1 colors.xml

<color>name 命名使用下劃線命名法闷沥,在你的 colors.xml 文件中應(yīng)該只是映射顏色的名稱一個(gè) ARGB 值,而沒有其它的咐容。不要使用它為不同的按鈕來定義 ARGB 值舆逃。

例如,不要像下面這樣做:

  <resources>
      <color name="button_foreground">#FFFFFF</color>
      <color name="button_background">#2A91BD</color>
      <color name="comment_background_inactive">#5F5F5F</color>
      <color name="comment_background_active">#939393</color>
      <color name="comment_foreground">#FFFFFF</color>
      <color name="comment_foreground_important">#FF9D2F</color>
      ...
      <color name="comment_shadow">#323232</color>

使用這種格式戳粒,會(huì)非常容易重復(fù)定義 ARGB 值路狮,而且如果應(yīng)用要改變基色的話會(huì)非常困難。同時(shí)蔚约,這些定義是跟一些環(huán)境關(guān)聯(lián)起來的奄妨,如 button 或者 comment,應(yīng)該放到一個(gè)按鈕風(fēng)格中苹祟,而不是在 colors.xml 文件中砸抛。

相反,應(yīng)該這樣做:

  <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>

向應(yīng)用設(shè)計(jì)者那里要這個(gè)調(diào)色板树枫,名稱不需要跟 "green"直焙、"blue" 等等相同。"brand_primary"砂轻、"brand_secondary"奔誓、"brand_negative" 這樣的名字也是完全可以接受的。像這樣規(guī)范的顏色很容易修改或重構(gòu)搔涝,會(huì)使應(yīng)用一共使用了多少種不同的顏色變得非常清晰厨喂。通常一個(gè)具有審美價(jià)值的 UI 來說,減少使用顏色的種類是非常重要的庄呈。

注意:如果某些顏色和主題有關(guān)蜕煌,那就單獨(dú)寫一個(gè) colors_theme.xml

5.6.2 dimens.xml

像對(duì)待 colors.xml 一樣對(duì)待 dimens.xml 文件诬留,與定義顏色調(diào)色板一樣幌绍,你同時(shí)也應(yīng)該定義一個(gè)空隙間隔和字體大小的“調(diào)色板”颁褂。 一個(gè)好的例子故响,如下所示:

<resources>

    <!-- font sizes -->
    <dimen name="font_22">22sp</dimen>
    <dimen name="font_18">18sp</dimen>
    <dimen name="font_15">15sp</dimen>
    <dimen name="font_12">12sp</dimen>

    <!-- typical spacing between two views -->
    <dimen name="spacing_40">40dp</dimen>
    <dimen name="spacing_24">24dp</dimen>
    <dimen name="spacing_14">14dp</dimen>
    <dimen name="spacing_10">10dp</dimen>
    <dimen name="spacing_4">4dp</dimen>

    <!-- typical sizes of views -->
    <dimen name="button_height_60">60dp</dimen>
    <dimen name="button_height_40">40dp</dimen>
    <dimen name="button_height_32">32dp</dimen>

</resources>

布局時(shí)在寫 marginspaddings 時(shí)傀广,你應(yīng)該使用 spacing_xx 尺寸格式來布局,而不是像對(duì)待 string 字符串一樣直接寫值彩届,像這樣規(guī)范的尺寸很容易修改或重構(gòu)伪冰,會(huì)使應(yīng)用所有用到的尺寸一目了然。 這樣寫會(huì)非常有感覺樟蠕,會(huì)使組織和改變風(fēng)格或布局非常容易贮聂。

5.6.3 strings.xml

<string>name 命名使用下劃線命名法,采用以下規(guī)則:{模塊名_}邏輯名稱寨辩,這樣方便同一個(gè)界面的所有 string 都放到一起吓懈,方便查找。

名稱 說明
main_menu_about 主菜單按鍵文字
friend_title 好友模塊標(biāo)題欄
friend_dialog_del 好友刪除提示
login_check_email 登錄驗(yàn)證
dialog_title 彈出框標(biāo)題
button_ok 確認(rèn)鍵
loading 加載文字
5.6.4 styles.xml

<style>name 命名使用大駝峰命名法靡狞,幾乎每個(gè)項(xiàng)目都需要適當(dāng)?shù)氖褂?styles.xml 文件耻警,因?yàn)閷?duì)于一個(gè)視圖來說,有一個(gè)重復(fù)的外觀是很常見的甸怕,將所有的外觀細(xì)節(jié)屬性(colors甘穿、paddingfont)放在 styles.xml 文件中梢杭。 在應(yīng)用中對(duì)于大多數(shù)文本內(nèi)容温兼,最起碼你應(yīng)該有一個(gè)通用的 styles.xml 文件,例如:

<style name="ContentText">
    <item name="android:textSize">@dimen/font_normal</item>
    <item name="android:textColor">@color/basic_black</item>
</style>

應(yīng)用到 TextView 中:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/price"
    style="@style/ContentText"
    />

或許你需要為按鈕控件做同樣的事情武契,不要停止在那里募判,將一組相關(guān)的和重復(fù) android:xxxx 的屬性放到一個(gè)通用的 <style> 中。

5.7 id 命名

命名規(guī)則:view 縮寫{_模塊名}_邏輯名咒唆,例如: btn_main_search届垫、btn_back

如果在項(xiàng)目中有用黃油刀的話钧排,使用 AS 的插件:ButterKnife Zelezny敦腔,可以非常方便幫助你生成注解;沒用黃油刀的話可以使用 Android Code Generator 插件恨溜。

6 版本統(tǒng)一規(guī)范

Android 開發(fā)存在著眾多版本的不同符衔,比如 compileSdkVersionminSdkVersion糟袁、targetSdkVersion 以及項(xiàng)目中依賴第三方庫的版本判族,不同的 module 及不同的開發(fā)人員都有不同的版本,所以需要一個(gè)統(tǒng)一版本規(guī)范的文件项戴。

具體可以參考我寫的這篇博文:[Android 開發(fā)之版本統(tǒng)一規(guī)范][Android 開發(fā)之版本統(tǒng)一規(guī)范]形帮。

如果是開發(fā)多個(gè)系統(tǒng)級(jí)別的應(yīng)用,當(dāng)多個(gè)應(yīng)用同時(shí)用到相同的 so 庫時(shí),一定要確保 so 庫的版本一致辩撑,否則可能會(huì)引發(fā)應(yīng)用崩潰界斜。

7 第三方庫規(guī)范

別再閉門造車了,用用最新最火的技術(shù)吧合冀,安利一波:[Android 流行框架查速表][Android 流行框架查速表]各薇,順便帶上自己的干貨:[Android 開發(fā)人員不得不收集的代碼][Android 開發(fā)人員不得不收集的代碼]

希望 Team 能用時(shí)下較新的技術(shù)君躺,對(duì)開源庫的選取峭判,一般都需要選擇比較穩(wěn)定的版本,作者在維護(hù)的項(xiàng)目棕叫,要考慮作者對(duì) issue 的解決林螃,以及開發(fā)者的知名度等各方面。選取之后俺泣,一定的封裝是必要的疗认。

個(gè)人推薦 Team 可使用如下優(yōu)秀輪子:

  • [Retrofit][Retrofit]
  • [RxAndroid][RxAndroid]
  • [OkHttp][OkHttp]
  • [Glide][Glide]/[Fresco][Fresco]
  • [Gson][Gson]/[Fastjson][Fastjson]
  • [EventBus][EventBus]/[AndroidEventBus][AndroidEventBus]
  • [GreenDao][GreenDao]
  • [Dagger2][Dagger2](選用)
  • [Tinker][Tinker](選用)

8 注釋規(guī)范

為了減少他人閱讀你代碼的痛苦值,請(qǐng)?jiān)陉P(guān)鍵地方做好注釋砌滞。

8.1 類注釋

每個(gè)類完成后應(yīng)該有作者姓名和聯(lián)系方式的注釋侮邀,對(duì)自己的代碼負(fù)責(zé)。

/**
 * <pre>
 *     author : Blankj
 *     e-mail : xxx@xx
 *     time   : 2017/03/07
 *     desc   : xxxx 描述
 *     version: 1.0
 * </pre>
 */
public class WelcomeActivity {
    ...
}

具體可以在 AS 中自己配制贝润,進(jìn)入 Settings -> Editor -> File and Code Templates -> Includes -> File Header绊茧,輸入

/**
 * <pre>
 *     author : ${USER}
 *     e-mail : xxx@xx
 *     time   : ${YEAR}/${MONTH}/${DAY}
 *     desc   :
 *     version: 1.0
 * </pre>
 */

這樣便可在每次新建類的時(shí)候自動(dòng)加上該頭注釋。

8.2 方法注釋

每一個(gè)成員方法(包括自定義成員方法打掘、覆蓋方法华畏、屬性方法)的方法頭都必須做方法頭注釋,在方法前一行輸入 /** + 回車 或者設(shè)置 Fix doc comment(Settings -> Keymap -> Fix doc comment)快捷鍵尊蚁,AS 便會(huì)幫你生成模板亡笑,我們只需要補(bǔ)全參數(shù)即可,如下所示横朋。

/**
 * bitmap 轉(zhuǎn) byteArr
 *
 * @param bitmap bitmap 對(duì)象
 * @param format 格式
 * @return 字節(jié)數(shù)組
 */
public static byte[] bitmap2Bytes(Bitmap bitmap, CompressFormat format) {
    if (bitmap == null) return null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(format, 100, baos);
    return baos.toByteArray();
}

8.3 塊注釋

塊注釋與其周圍的代碼在同一縮進(jìn)級(jí)別仑乌。它們可以是 /* ... */ 風(fēng)格,也可以是 // ... 風(fēng)格(// 后最好帶一個(gè)空格)琴锭。對(duì)于多行的 /* ... */ 注釋晰甚,后續(xù)行必須從 * 開始, 并且與前一行的 * 對(duì)齊决帖。以下示例注釋都是 OK 的厕九。

/*
 * This is
 * okay.
 */

// And so
// is this.

/* Or you can
* even do this. */

注釋不要封閉在由星號(hào)或其它字符繪制的框架里。

Tip:在寫多行注釋時(shí)地回,如果你希望在必要時(shí)能重新?lián)Q行(即注釋像段落風(fēng)格一樣)扁远,那么使用 /* ... */俊鱼。

8.4 其他一些注釋

AS 已幫你集成了一些注釋模板,我們只需要直接使用即可畅买,在代碼中輸入 todo并闲、fixme 等這些注釋模板,回車后便會(huì)出現(xiàn)如下注釋皮获。

// TODO: 17/3/14 需要實(shí)現(xiàn)焙蚓,但目前還未實(shí)現(xiàn)的功能的說明
// FIXME: 17/3/14 需要修正,甚至代碼是錯(cuò)誤的洒宝,不能工作,需要修復(fù)的說明

9 測(cè)試規(guī)范

業(yè)務(wù)開發(fā)完成之后萌京,開發(fā)人員做單元測(cè)試雁歌,單元測(cè)試完成之后,保證單元測(cè)試全部通過知残,同時(shí)單元測(cè)試代碼覆蓋率達(dá)到一定程度(這個(gè)需要開發(fā)和測(cè)試約定靠瞎,理論上越高越好),開發(fā)提測(cè)求妹。

9.1 單元測(cè)試

測(cè)試類的名稱應(yīng)該是所測(cè)試類的名稱加 Test乏盐,我們創(chuàng)建 DatabaseHelper 的測(cè)試類,其名應(yīng)該叫 DatabaseHelperTest制恍。

測(cè)試函數(shù)被 @Test 所注解父能,函數(shù)名通常以被測(cè)試的方法為前綴,然后跟隨是前提條件和預(yù)期的結(jié)果净神。

  • 模板:void methodName 前提條件和預(yù)期結(jié)果()
  • 例子:void signInWithEmptyEmailFails()

注意:如果函數(shù)足夠清晰何吝,那么前提條件和預(yù)期的結(jié)果是可以省略的。

有時(shí)一個(gè)類可能包含大量的方法鹃唯,同時(shí)需要對(duì)每個(gè)方法進(jìn)行幾次測(cè)試爱榕。在這種情況下,建議將測(cè)試類分成多個(gè)類坡慌。例如黔酥,如果 DataManager 包含很多方法,我們可能要把它分成 DataManagerSignInTest洪橘、DataManagerLoadUsersTest 等等跪者。

9.2 Espresso 測(cè)試

每個(gè) Espresso 測(cè)試通常是針對(duì) Activity,所以其測(cè)試名就是其被測(cè)的 Activity 的名稱加 Test梨树,比如 SignInActivityTest坑夯。

10 其他的一些規(guī)范

  1. 合理布局,有效運(yùn)用 <merge>抡四、<ViewStub>柜蜈、<include> 標(biāo)簽仗谆;

  2. ActivityFragment 里面有許多重復(fù)的操作以及操作步驟,所以我們都需要提供一個(gè) BaseActivity

轉(zhuǎn)載地址

Blankj/AndroidStandardDevelop: :star2: Best practices in Android develop(final).
https://github.com/Blankj/AndroidStandardDevelop

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末淑履,一起剝皮案震驚了整個(gè)濱河市隶垮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秘噪,老刑警劉巖狸吞,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異指煎,居然都是意外死亡蹋偏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門至壤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來威始,“玉大人,你說我怎么就攤上這事像街±杼模” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵镰绎,是天一觀的道長(zhǎng)脓斩。 經(jīng)常有香客問我,道長(zhǎng)畴栖,這世上最難降的妖魔是什么随静? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮驶臊,結(jié)果婚禮上挪挤,老公的妹妹穿的比我還像新娘。我一直安慰自己关翎,他們只是感情好扛门,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纵寝,像睡著了一般论寨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爽茴,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天葬凳,我揣著相機(jī)與錄音,去河邊找鬼室奏。 笑死火焰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胧沫。 我是一名探鬼主播昌简,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼占业,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了纯赎?” 一聲冷哼從身側(cè)響起谦疾,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎犬金,沒想到半個(gè)月后念恍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晚顷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年峰伙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片音同。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡词爬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出权均,到底是詐尸還是另有隱情,我是刑警寧澤锅锨,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布叽赊,位于F島的核電站,受9級(jí)特大地震影響必搞,放射性物質(zhì)發(fā)生泄漏必指。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一恕洲、第九天 我趴在偏房一處隱蔽的房頂上張望塔橡。 院中可真熱鬧,春花似錦霜第、人聲如沸葛家。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽癞谒。三九已至,卻和暖如春刃榨,著一層夾襖步出監(jiān)牢的瞬間弹砚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工枢希, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留桌吃,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓苞轿,卻偏偏與公主長(zhǎng)得像茅诱,于是被迫代替她去往敵國和親逗物。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355