kotlin-開發(fā)規(guī)范

  1. 前言
    為了有利于項(xiàng)目維護(hù)、增強(qiáng)代碼可讀性、提升 Code Review 效率以及規(guī)范團(tuán)隊(duì)安卓開發(fā),故提出以下安卓開發(fā)規(guī)范。

  2. 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)化;

  3. 命名規(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)。

  1. 代碼樣式規(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;
                 }
            });
}

  1. 資源文件規(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。

  1. 注釋規(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 代碼塊注釋
寫出代碼的目的,而不是行為,行為可以通過具體的代碼來判斷。

  1. 版本統(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"
}

  1. 第三方庫規(guī)范
    對(duì)開源庫的選取,一般都需要選擇比較穩(wěn)定的版本,作者在維護(hù)的項(xiàng)目,要考慮作者對(duì) issue 的解決,以及開發(fā)者的知名度等各方面。選取之后,一定的封裝是必要的。

如下優(yōu)秀輪子:

Retrofit
RxAndroid
OkHttp
Glide/Fresco
Gson/Fastjson
EventBus/AndroidEventBus

  1. 項(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)。

  1. 組件化規(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

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容