前言
為了有利于項(xiàng)目維護(hù)、增強(qiáng)代碼可讀性、提升 Code Review 效率以及規(guī)范團(tuán)隊(duì)安卓開發(fā),故提出以下安卓開發(fā)規(guī)范。Android Studio 規(guī)范
盡量使用最新的穩(wěn)定版 Android Studio 進(jìn)行開發(fā);
編碼格式統(tǒng)一為 UTF-8;
編輯完 .java、.xml 等文件后一定要 格式化,格式化,格式化(如果團(tuán)隊(duì)有公共的樣式包,那就遵循它,否則統(tǒng)一使用 AS 默認(rèn)模板即可,在 Android Studio 中,
Mac 下可以使用快捷鍵 cmd + alt + L 進(jìn)行代碼格式化,
Window 下可以使用快捷鍵 ctrl + alt + L 進(jìn)行代碼格式化);
刪除多余的 import,減少警告出現(xiàn),
Mac 下可以使用快捷鍵 ctrl + alt + O 進(jìn)行 import 優(yōu)化,
Window 下可以使用快捷鍵 ctrl + alt + O 進(jìn)行 import 優(yōu)化;命名規(guī)范
代碼中的命名嚴(yán)禁使用拼音與英文混合的方式,更不允許直接使用中文的方式。正確的英文拼寫和語法可以讓閱讀者易于理解,避免歧義。
注意:即使純拼音命名方式也要避免采用。但 alibaba、taobao、youku、hangzhou 等國際通用的名稱,可視同英文。
3.1 包名
包名全部小寫,連續(xù)的單詞只是簡(jiǎn)單地連接起來,不使用下劃線,采用反域名命名規(guī)則,全部使用小寫字母。一級(jí)包名是頂級(jí)域名,通常為 com、edu、gov、net、org 等,二級(jí)包名為公司名,三級(jí)包名根據(jù)應(yīng)用進(jìn)行命名,后面就是對(duì)包名的劃分了,關(guān)于包名的劃分,推薦采用 PBF(按功能分包 Package By Feature)。
3.2 類名
類名通常是名詞或名詞短語,接口名稱有時(shí)可能是形容詞或形容詞短語?,F(xiàn)在還沒有特定的規(guī)則或行之有效的約定來命名注解類型。
名詞,采用大駝峰命名法,盡量避免縮寫,除非該縮寫是眾所周知的, 比如 HTML、URL,如果類名稱中包含單詞縮寫,則單詞縮寫的每個(gè)字母均應(yīng)大寫。
測(cè)試類的命名以它要測(cè)試的類的名稱開始,以 Test 結(jié)束。例如:HashTest 或 HashIntegrationTest。
接口(interface):命名規(guī)則與類一樣采用大駝峰命名法,多以 able 或 ible 結(jié)尾,如 interface Runnable、interface Accessible;或者以 I 為前綴。
| 類 | 描述 | 示例 |
|---|---|---|
| Activity 類 | 以Activity 為后綴標(biāo)識(shí) | 歡迎頁面類 WelcomeActivity |
| Adapter 類 | 以Adapter 為后綴標(biāo)識(shí) | 新聞詳情適配器NewsDetailAdapter |
| 解析類 | 以Parser 為后綴標(biāo)識(shí) | 首頁解析類 HomePosterParser |
| 工具方法類 | 以Util、Tool、Manager 為后綴標(biāo)識(shí) | 線程池管理類:ThreadPoolManager,日志工具類:LogUtil,網(wǎng)絡(luò)請(qǐng)求工具類:HttpTool |
| 數(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 |
fix:這里是否需要注明使用組件化時(shí),組件對(duì)外提供的接口和實(shí)現(xiàn)類命名。
補(bǔ)充:表格中放不下,特意放在下面。上面提到工具類以 Util 和 Tool 為后綴,那么 Util 和 Tool 的區(qū)別是什么?Util 是無業(yè)務(wù)邏輯的,Tool 是有業(yè)務(wù)邏輯的。比如 HttpUtil 只是包含了基本網(wǎng)絡(luò)請(qǐng)求,而 HttpTool 中包含了項(xiàng)目的一些配置,如在每個(gè)請(qǐng)求增加 token 。也可以這么說,HttpUtil 可以跨項(xiàng)目使用,而 HttpTool 只能在該項(xiàng)目中使用。
3.3 方法名
方法名都以 lowerCamelCase 風(fēng)格編寫。
方法名通常是動(dòng)詞或動(dòng)詞短語。
| 方法 | 說明 |
|---|---|
| initXX() | 初始化相關(guān)方法,如初始化布局 initView() |
| isXX(), checkXX() | 方法返回值為 boolean 型 |
| handleXX(), processXX() | 對(duì)數(shù)據(jù)進(jìn)行處理的方法 |
| displayXX(), showXX() | 彈出提示框和提示信息 |
| resetXX() | 重置數(shù)據(jù) |
| clearXX() | 清除數(shù)據(jù) |
| drawXX() | 繪制數(shù)據(jù)或效果相關(guān)的 |
| setXX() | 設(shè)置某個(gè)屬性值 |
| getXX() | 返回某個(gè)值或單個(gè)對(duì)象 |
| listXX() | 返回多個(gè)對(duì)象 |
| countXX() | 返回統(tǒng)計(jì)值 |
| saveXX(), insertXX() | 保存或插入數(shù)據(jù) |
| removeXX(), deleteXX() | 移除數(shù)據(jù)或者視圖等,如 removeView() |
| updateXX() | 更新數(shù)據(jù) |
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)行正確的斷句。
通過IDE 自動(dòng)生成get 、set 和構(gòu)造函數(shù)的時(shí)候,這個(gè)沒有任何實(shí)際意義的m前綴會(huì)被包含到變量名稱當(dāng)中去,顯得很low也很容易影響可讀性。在 AS 中,Settings -> Editor -> Code Style -> Java -> Code Generation 中,F(xiàn)ield Name prefix 設(shè)置 m,Static Field Name prefix 設(shè)置 s。這樣 AS 就可以識(shí)別了,自動(dòng)生成方法的時(shí)候會(huì)去掉 s 或 m。
3.5.2 Type0(控件類型)
考慮到 Android 眾多的 UI 控件,為避免控件和普通成員變量混淆以及更好地表達(dá)意思,所有用來表示控件的成員變量統(tǒng)一加上控件縮寫作為前綴(具體見附錄 [UI 控件縮寫表](#UI 控件縮寫表))。
例如:mIvAvatar、rvBooks、flContainer。
3.5.3 VariableName(變量名)
變量名中可能會(huì)出現(xiàn)量詞,我們需要?jiǎng)?chuàng)建統(tǒng)一的量詞,它們更容易理解,也更容易搜索。
例如:mFirstBook、mPreBook、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。
例如:mIvAvatarList、userArr、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、j、k、m 和 n,它們一般用于整型;c、d、e,它們一般用于字符型。 如:for (int i = 0; i < len; i++)。
3.9 類型變量名
類型變量可用以下兩種風(fēng)格之一進(jìn)行命名:
單個(gè)的大寫字母,后面可以跟一個(gè)數(shù)字(如:E, T, X, T2)。
以類命名方式(參考[3.2 類名](#3.2 類名)),后面加個(gè)大寫的 T(如:RequestT, FooBarT)。
- 代碼樣式規(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();
}
1
2
3
同樣也接受以下樣式:
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ì)其拆解,一個(gè)方法最好只做一件事情。
4.3 類成員的順序
這并沒有唯一的正確解決方案,但如果都使用一致的順序?qū)?huì)提高代碼的可讀性,推薦使用如下排序:
1.常量
2.字段(public -> protected -> private)
3.構(gòu)造函數(shù)
4.重寫函數(shù)和回調(diào) (在Android 中,應(yīng)該將生命周期的函數(shù)放在前面)
5.公有函數(shù)
6.私有函數(shù)
7.內(nèi)部類或接口
例如:
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
public Long updateTime;
protected String mContent;
private String mTitle;
private TextView mTextViewTitle;
@Override
public void onCreate() {
...
}
public void setTitle(String title) {
mTitle = title;
}
private void setUpView() {
...
}
static class AnInnerClass {
}
}
如果類繼承于 Android 組件(例如 Activity 或 Fragment),那么把重寫函數(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) Activity 或 Fragment 傳遞數(shù)據(jù)通過 Intent 或 Bundle 時(shí),不同值的鍵須遵循上一條所提及到的。
當(dāng) Activity 或 Fragment 啟動(dòng)需要傳遞參數(shù)時(shí),那么它需要提供一個(gè) public static 的函數(shù)來幫助啟動(dòng)或創(chuàng)建它。
這方面,AS 已幫你寫好了相關(guān)的 Live Templates(只支持Java,不支持Kotlin),啟動(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() 之前的類的頂部;如果我們使用了這種方式,那么 extras 和 arguments 的鍵應(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.2 操作符的換行
除賦值操作符之外,我們把換行符放在操作符之前,例如:
int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne
+ theFinalOne;
賦值操作符的換行我們放在其后,例如:
int longName =
anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne;
4.7.3 函數(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.4 多參數(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.5 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;
}
});
}
- 資源文件規(guī)范
資源文件命名為全部小寫,采用下劃線命名法。
如果是三方庫開發(fā),其使用到的資源文件及相關(guān)的 name 都應(yīng)該使用庫名作為前綴,這樣做可以避免三方庫資源和實(shí)際應(yīng)用資源重名的沖突。
如果想對(duì)資源文件進(jìn)行分包,可以
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.xml、market_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 控件縮寫表](#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.3.1 圖片位置
大分辨率圖片(單維度超過 1000)大分辨率圖片建議統(tǒng)一放在 xxhdpi 目錄
下管理,否則將導(dǎo)致占用內(nèi)存成倍數(shù)增加 。
正例:
將 144144 的應(yīng)用圖標(biāo) PNG 文件放在 drawable-xxhdpi 目錄
反例:
將 144144 的應(yīng)用圖標(biāo) PNG 文件放在 drawable-mhdpi 目錄
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.xml、styles_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í)在寫 margins 和 paddings 時(shí),你應(yīng)該使用 spacing_xx 尺寸格式來布局,而不是像對(duì)待 string 字符串一樣直接寫值,像這樣規(guī)范的尺寸很容易修改或重構(gòu),會(huì)使應(yīng)用所有用到的尺寸一目了然。 這樣寫會(huì)非常有感覺,會(huì)使組織和改變風(fēng)格或布局非常容易。
5.6.3 styles.xml
<style> 的 name 命名使用大駝峰命名法,幾乎每個(gè)項(xiàng)目都需要適當(dāng)?shù)氖褂?styles.xml 文件,因?yàn)閷?duì)于一個(gè)視圖來說,有一個(gè)重復(fù)的外觀是很常見的,將所有的外觀細(xì)節(jié)屬性(colors、padding、font)放在 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 命名
5.7.1 java項(xiàng)目
命名規(guī)則:view 縮寫{模塊名}邏輯名,例如: btn_main_search、btn_back。
如果在項(xiàng)目中有用黃油刀的話,使用 AS 的插件:ButterKnife Zelezny,可以非常方便幫助你生成注解;沒用黃油刀的話可以使用 Android Code Generator 插件。
5.7.2 kotlin項(xiàng)目
插件 apply plugin: 'kotlin-android-extensions',可以在代碼中通過 xml 定義的控件 id 直接操作控件,而不用寫 findViewById ,所以這里控件的命名直接使用 lowerCamelCase 風(fēng)格編寫。
命名規(guī)則:view 縮寫{模塊名}邏輯名,例如: btnMainSearch、btnBack。
- 注釋規(guī)范
6.1 類注釋
每個(gè)類完成后應(yīng)該有作者姓名的注釋,對(duì)自己的代碼負(fù)責(zé)。
/**
* <pre>
* author : Blankj
* 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}
* time : ${YEAR}/${MONTH}/${DAY}
* desc :
* version: 1.0
* </pre>
*/
這樣便可在每次新建類的時(shí)候自動(dòng)加上該頭注釋。
6.2 函數(shù)的注釋
類成員變量、公有和保護(hù)方法必須需要寫注釋,寫在被注釋元素的上面,并與其上的代碼用空行隔開,注釋與所描述內(nèi)容進(jìn)行同樣的縮進(jìn)排序。
私有變量必須寫注釋,私有方法,如果方法命名能清晰的表達(dá)方法的功能,不需要寫注釋。
公有和保護(hù)方法注釋需要列出方法的一句話功能簡(jiǎn)述、功能詳細(xì)描述、輸入?yún)?shù)、輸出參數(shù)、返回值、異常等。
對(duì)于方法內(nèi)部用 throw 語句拋出的異常,必須在方法的注釋中標(biāo)明,對(duì)于所調(diào)用的其他方法所拋出的異常,選擇主要的在注釋中說明。用 @exception 標(biāo)注 Runtime 異常,@throws 標(biāo)注非 Runtime 異常。異常的注釋必須說明該異常的含義和什么條件下拋出該異常。
格式如下:
/**
* 一句話功能描述
* 功能詳細(xì)描述
* @param [參數(shù)1] [參數(shù)1說明]
* @param [參數(shù)2] [參數(shù)2說明]
* @return [返回類型說明]
* @exception/throws [異常類型] [異常說明]
* @see [類、類#方法、類#成員]
* @since [起始版本]
* @deprecated [是否廢棄]
*/
6.3 代碼塊注釋
寫出代碼的目的,而不是行為,行為可以通過具體的代碼來判斷。
- 版本統(tǒng)一規(guī)范
Android 開發(fā)存在著眾多版本的不同,比如 compileSdkVersion、minSdkVersion、targetSdkVersion 以及項(xiàng)目中依賴第三方庫的版本,不同的 module 及不同的開發(fā)人員都有不同的版本,所以需要一個(gè)統(tǒng)一版本規(guī)范的文件。
可以在項(xiàng)目根目錄下 build.gradle文件中增加一個(gè):
ext {
compile_sdk_version = 27
min_sdk_version = 16
target_sdk_version = 27
support_version = '27.1.1'
}
或者新建一個(gè) config.gradle 文件,將上面的代碼放在其中,在項(xiàng)目根目錄下 build.gradle文件頂部增加 apply from: "config.gradle"
在 module 的 build.gradle 中引用:
android {
compileSdkVersion compile_sdk_version
defaultConfig {
minSdkVersion min_sdk_version
targetSdkVersion target_sdk_version
}
}
dependencies {
Implementation "com.android.support:appcompat-v7:$support_version"
Implementation "com.android.support:support-v4:$support_version"
}
- 第三方庫規(guī)范
對(duì)開源庫的選取,一般都需要選擇比較穩(wěn)定的版本,作者在維護(hù)的項(xiàng)目,要考慮作者對(duì) issue 的解決,以及開發(fā)者的知名度等各方面。選取之后,一定的封裝是必要的。
如下優(yōu)秀輪子:
Retrofit
RxAndroid
OkHttp
Glide/Fresco
Gson/Fastjson
EventBus/AndroidEventBus
- 項(xiàng)目規(guī)范
9.1 UI
使用 start 和 end 替代 left 和 right,使布局能適應(yīng) RightRoLeft布局。
FrameLayout 默認(rèn)是左上,切換到 RTL 也是左上,所以必須顯示的指明布局 android:layout_gravity="start";
合理布局,有效運(yùn)用 <merge>、<ViewStub>、<include> 標(biāo)簽;
比如content 是一個(gè) FrameLayout ,所以這里簡(jiǎn)單布局是不需要外層ViewGroup,直接使用 <merge> 來作為布局文件的根ViewGroup就可以了;
所有布局都需要考慮到大屏幕和小屏幕顯示的問題,尤其是對(duì)大屏幕一個(gè)頁面就可以展示完,而對(duì)于小屏幕不能展示完,需要增加 <ScrollView> 讓頁面能夠滾動(dòng)。目前一般情況下最小屏幕是 1280 * 720,如果要考慮極端情況的話,嘗試支持 320 * 480 的屏幕。
字體單位使用 dp 設(shè)置字體而不是 sp。
對(duì)于設(shè)計(jì)圖上按鈕大小小于 24dp * 24dp,應(yīng)該使用 padding 將按鈕的實(shí)際大小控制在大于 24dp * 24dp。
常見布局只使用 FrameLayout、LinearLayout、FlexboxLayout、ConstraintLayout。
不要過分依賴通用資源,否則會(huì)導(dǎo)致修改困難,該拆分的就拆分,不要在乎資源內(nèi)容是一樣的。
所有的文本按鈕,還是使用 Button,不要使用 TextView ,畢竟系統(tǒng)對(duì) Button 有樣式渲染。同理對(duì)于圖片按鈕,應(yīng)該使用 ImageButton 而不是 ImageView。
使用Space控件占據(jù)不顯示內(nèi)容的空間。
如果是背景色是白色,那么就不要設(shè)置了
ScrollView 內(nèi)部嵌套有 ListView 或 RecycleView 等,注意要考慮到ScrollView默認(rèn)位置不是最頂部的情況。
考慮過渡繪制,不要直接在整個(gè)布局增加背景顏色,考慮是否在布局的一部分設(shè)置背景顏色就可以達(dá)到UI效果。
9.2 資源
9.2.1 文本和顏色不能使用硬編碼
將硬編碼的文字和顏色放入資源文件中進(jìn)行管理,減少定義的顏色,合并類似的,這里如果是使用 Android 系統(tǒng)自帶的,全部自己定義,防止出錯(cuò)。
9.2.2 管理資源文件
一個(gè) Module 的資源文件都在 res 目錄下,如果一個(gè) Module 涉及到的頁面很多,資源文件很多,不方便管理,可以多配置幾個(gè)資源文件目錄,這樣我們可以對(duì)每個(gè)模塊的資源都進(jìn)行具體分類。
方法很簡(jiǎn)單,配置我們的app文件夾下的 build.gradle 文件,比如:
android {
...
sourceSets {
main {
res.srcDirs('src/main/res', 'src/main/res_core', 'src/main/res_sub')
}
}
}
配置完之后,sync project 一下就成功了。
9.3 代碼規(guī)范
1.Android的最小兼容版本到17.
關(guān)于Android不同系統(tǒng)版本的市場(chǎng)占比情況詳解
2.Activity 和 Fragment 里面有許多重復(fù)的操作以及操作步驟,所以我們都需要提供一個(gè) BaseActivity 和 BaseFragment,讓所有的 Activity 和 Fragment 都繼承這個(gè)基類。
3.必須支持界面被系統(tǒng)回收,用戶再次打開App的時(shí)候能夠恢復(fù)用戶當(dāng)時(shí)的使用狀態(tài),分析出具體在哪些情況下需要,哪些情況下不需要。
例如彈窗,恢復(fù)彈窗上顯示的數(shù)據(jù),恢復(fù)彈窗的按鈕的點(diǎn)擊事件。
4.使用Gson中的 @SerializedName 將服務(wù)器端返回?cái)?shù)據(jù)字段不符合命名規(guī)范的轉(zhuǎn)換為符合規(guī)范的命名,分離服務(wù)器和客戶端字段的硬綁定。
5.使用ArrayMap、ArraySet、SparseArray替換HashMap<T, T>、HashMap<int, T> 和 HashSet<T>。
6.多用組合,少用繼承;
7.方法基本上都按照調(diào)用的先后順序在各自區(qū)塊中排列;
8.當(dāng)一個(gè)類有多個(gè)構(gòu)造函數(shù),或是多個(gè)同名函數(shù),這些函數(shù)應(yīng)該按順序出現(xiàn)在一起,中間不要放進(jìn)其它函數(shù);
9.數(shù)據(jù)提供統(tǒng)一的入口。無論是在 MVP、MVC 還是 MVVM 中,提供一個(gè)統(tǒng)一的數(shù)據(jù)入口,都可以讓代碼變得更加易于維護(hù)。比如可使用一個(gè) DataManager,把 http、preference、eventpost、database 都放在 DataManager 里面進(jìn)行操作,我們只需要與 DataManager 打交道;
10.提取方法,去除重復(fù)代碼。對(duì)于必要的工具類抽取也很重要,這在以后的項(xiàng)目中是可以重用的。
11.項(xiàng)目引入 RxAndroid 響應(yīng)式編程,可以極大的減少邏輯代碼;
12.通過引入事件總線,如:EventBus、AndroidEventBus、RxBus,它允許我們?cè)?DataLayer 中發(fā)送事件,以便 ViewLayer 中的多個(gè)組件都能夠訂閱到這些事件,減少回調(diào);
13.盡可能使用局部變量;
14.及時(shí)關(guān)閉流;
15.盡量減少對(duì)變量的重復(fù)計(jì)算;
如下面的操作:
for (int i = 0; i < list.size(); i++) {
...
}
建議替換為:
for (int i = 0, len = list.size(); i < len; i++) {
...
}
盡量采用懶加載的策略,即在需要的時(shí)候才創(chuàng)建;
例如:
String str = "aaa";
if (i == 1) {
list.add(str);
}
建議替換為:
if (i == 1) {
String str = "aaa";
list.add(str);
}
不要在循環(huán)中使用 try…catch…,應(yīng)該把其放在最外層;
使用帶緩沖的輸入輸出流進(jìn)行 IO 操作;
盡量在合適的場(chǎng)合使用單例;
使用單例可以減輕加載的負(fù)擔(dān)、縮短加載的時(shí)間、提高加載的效率,但并不是所有地方都適用于單例,簡(jiǎn)單來說,單例主要適用于以下三個(gè)方面:
控制資源的使用,通過線程同步來控制資源的并發(fā)訪問。
控制實(shí)例的產(chǎn)生,以達(dá)到節(jié)約資源的目的。
控制數(shù)據(jù)的共享,在不建立直接關(guān)聯(lián)的條件下,讓多個(gè)不相關(guān)的進(jìn)程或線程之間實(shí)現(xiàn)通信。
使用 AS 自帶的 Lint 來優(yōu)化代碼結(jié)構(gòu)(右鍵 module、目錄或者文件,選擇 Analyze -> Inspect Code);
內(nèi)存泄漏的檢測(cè);
Kotlin 和 Java 是兩種語言,在使用Kotlin的時(shí)候應(yīng)該使用Kotlin中的特性,而不是固執(zhí)的使用Java特性。比如:對(duì)于變量的賦值,如果僅僅是賦值,那么應(yīng)該直接開放變量權(quán)限;如果涉及到一系列后續(xù)操作,那么使用方法。
自定義控件的自定義屬性,必須使用控件名稱作為前綴,否則容易造成同名屬性。
不復(fù)用字符串,每個(gè)組件維護(hù)自己的,不要嫌麻煩。
不可不知的 Android strings.xml 那些事
不要通過 Intent 在 Android 基礎(chǔ)組件之間傳遞大數(shù)據(jù)(binder transaction緩存為 1MB),可能導(dǎo)致 OOM。
新建線程時(shí),必須通過線程池提供(AsyncTask 或者 ThreadPoolExecutor或者其他形式自定義的線程池),不允許在應(yīng)用中自行顯式創(chuàng)建線程 。
子線程中不能更新界面,更新界面必須在主線程中進(jìn)行,網(wǎng)絡(luò)操作不能在主線程中調(diào)用 。
不要在非 UI 線程中初始化 ViewStub,否則會(huì)返回 null。
任何時(shí)候不要硬編碼文件路徑,請(qǐng)使用 Android 文件系統(tǒng) API 訪問。
示例:Android 應(yīng)用提供內(nèi)部和外部存儲(chǔ),分別用于存放應(yīng)用自身數(shù)據(jù)以及應(yīng)用產(chǎn)生的用
戶數(shù)據(jù)??梢酝ㄟ^相關(guān) API 接口獲取對(duì)應(yīng)的目錄,進(jìn)行文件操作。
android.os.Environment#getExternalStorageDirectory()
android.os.Environment#getExternalStoragePublicDirectory()
android.content.Context#getFilesDir()
android.content.Context#getCacheDir
當(dāng)使用外部存儲(chǔ)時(shí),必須檢查外部存儲(chǔ)的可用性 。
SharedPreference 中只能存儲(chǔ)簡(jiǎn)單數(shù)據(jù)類型(int、 boolean、 String 等),復(fù)雜數(shù)據(jù)類型建議使用文件、數(shù)據(jù)庫等其他方式存儲(chǔ) 。
SharedPreference 提 交 數(shù) 據(jù) 時(shí) , 盡 量 使 用 Editor#apply() , 而 非Editor#commit()。一般來講,僅當(dāng)需要確定提交結(jié)果,并據(jù)此有后續(xù)操作時(shí),才使用 Editor#commit()。
多線程操作寫入數(shù)據(jù)庫時(shí),需要使用事務(wù),以免出現(xiàn)同步問題 。
執(zhí)行 SQL 語句時(shí),應(yīng)使用 SQLiteDatabase#insert()、 update()、 delete(),不要使用SQLiteDatabase#execSQL(),以免 SQL 注入風(fēng)險(xiǎn)。
不要通過 Msg 傳遞大的對(duì)象,會(huì)導(dǎo)致內(nèi)存問題。
不能在 Activity 沒有完全顯示時(shí)顯示 PopupWindow 和 Dialog。
Activity 間的數(shù)據(jù)通信,對(duì)于數(shù)據(jù)量比較大的,避免使用 Intent + Parcelable的方式,可以考慮 EventBus 等替代方案,以免造成 TransactionTooLargeException 。
Activity#onSaveInstanceState()方法不是 Activity 生命周期方法,也不保證一定會(huì)被調(diào)用。它是用來在 Activity 被意外銷毀時(shí)保存 UI 狀態(tài)的,只能用于保存臨時(shí)性數(shù)據(jù),例如 UI 控件的屬性等,不能跟數(shù)據(jù)的持久化存儲(chǔ)混為一談。持久化存儲(chǔ)應(yīng)該在 Activity#onPause()/onStop()中實(shí)行 。
避免在 BroadcastReceiver#onReceive()中執(zhí)行耗時(shí)操作,如果有耗時(shí)工作,應(yīng)該創(chuàng)建 IntentService 完成,而不應(yīng)該在 BroadcastReceiver 內(nèi)創(chuàng)建子線程去做 。
不要在 Activity#onDestroy()內(nèi)執(zhí)行釋放資源的工作,例如一些工作線程的銷毀和停止,因?yàn)?onDestroy()執(zhí)行的時(shí)機(jī)可能較晚??筛鶕?jù)實(shí)際需要,在Activity#onPause()/onStop()中結(jié)合 isFinishing()的判斷來執(zhí)行。
不要在 Android 的 Application 對(duì)象中緩存數(shù)據(jù)?;A(chǔ)組件之間的數(shù)據(jù)共享請(qǐng)使用 Intent 等機(jī)制,也可使用 SharedPreferences 等數(shù)據(jù)持久化機(jī)制。
使用 Toast 時(shí),建議定義一個(gè)全局的 Toast 對(duì)象,這樣可以避免連續(xù)顯示Toast 時(shí)不能取消上一次 Toast 消息的情況(如果你有連續(xù)彈出 Toast 的情況,避免使用 Toast.makeText)。
- 組件化規(guī)范
10.1 資源文件
10.1.2 命名
因?yàn)槲覀儾鸱殖隽撕芏鄻I(yè)務(wù)組件和功能組件,在把這些組件合并到“app殼工程”時(shí)候就有可能會(huì)出現(xiàn)資源名沖突問題,例如A組件和B組件都有一張叫做“ic_back”的圖標(biāo),這時(shí)候在集成模式下打包APP就會(huì)編譯出錯(cuò)。所以,如果我們的項(xiàng)目使用了組件化,那么在[5. 資源文件規(guī)范](#5. 資源文件規(guī)范)的基礎(chǔ)上,在所有資源文件的名字前增加組件名作為前綴。
10.1.2 拆分
按照資源的使用情況將資源文件分為公用資源和資源自由資源;
字符串拆分要謹(jǐn)慎:不復(fù)用字符串,每個(gè)組件維護(hù)自己的,不要嫌麻煩。參考:不可不知的 Android strings.xml 那些事
10.2 服務(wù)
這里服務(wù)是指業(yè)務(wù)組件或功能組件對(duì)外提供的功能,在所有組件都依賴的 common 組件編寫功能接口,然后在對(duì)應(yīng)的組件實(shí)現(xiàn)該接口。通過第三方庫,比如 ARouter 來通過接口來調(diào)用實(shí)現(xiàn)類,實(shí)現(xiàn)代碼隔離。
附錄
UI 控件縮寫表
| 名稱 | 縮寫 |
|---|---|
| Button | btn |
| CheckBox | cb |
| EditText | et |
| FrameLayout | fl |
| GridView | gv |
| ImageButton | ib |
| ImageView | iv |
| LinearLayout | ll |
| ListView | lv |
| ProgressBar | pb |
| RadioButtion | rb |
| RecyclerView | rv |
| RelativeLayout | rl |
| ScrollView | sv |
| SeekBar | sb |
| Spinner | spn |
| TextView | tv |
| ToggleButton | tb |
| VideoView | vv |
| WebView | wv |
常見的英文單詞縮寫表
| 名稱 | 縮寫 | |
|---|---|---|
| average | avg | |
| background | bg | |
| buffer | buf | |
| control | ctrl | |
| current | cur | |
| default | def | |
| delete | del | |
| document | doc | |
| error | err | |
| escape | esc | |
| icon | ic | (主要用在 App 的圖標(biāo)) |
| increment | inc | |
| information | info | |
| initial | init | |
| image | img | |
| Internationalization | I18N | |
| length | len | |
| library | lib | |
| message | msg | |
| password | pwd | |
| position | pos | |
| previous | pre | |
| selector | sel | |
| server | srv | |
| string | str | |
| temporary | tmp | |
| window | win |
程序中使用單詞縮寫原則:不要用縮寫,除非該縮寫是約定俗成的。