前言
雖然我們項目的代碼時間并不長,也沒經過太多人手,但代碼的規范性依然堪憂,目前存在較多的比較自由的「代碼規范」,這非常不利于項目的維護,代碼可讀性也不夠高,
此外,客戶端和后端的研發模式也完全不同,后端研發基本都是基于 SOA 思想的,通常一個子系統 3 個人一起維護就已經是很充分的人力了,更多時候就是 1 個主力 + 1 個 backup 的人力配置。
而客戶端卻完全不同,大家的代碼都是相互交叉的,一個模塊的代碼可能要經歷數十人的蹂躪,所以形成一個一致的開發規范迫在眉睫。
為什么需要一致的代碼規范?
核心還是減少溝通成本,提升我們的 Code Review 效率,讓我們的代碼更加易于維護。此外,一個一致的代碼規范可以造成更少的 bug,也就意味著更節省時間和金錢。
當然,規范是約定的,本系列文字全是筆者多年來博采眾長,積累而成,所以有任何不同意見,歡迎評論拍磚。
1. Android 的工具規范
工欲善其事,必先利其器。
由于 Android 基本都基于 Android Studio 進行開發,所以工具規范全部以 Android Studio 為前提。
- 必須使用最新的穩定版本的 Android Studio 進行開發;
- 編碼格式必須統一為 UTF-8;
-
刪除多余的 import,減少警告出現,可利用 AS 的 Optimize Imports(Settings -> Keymap -> Optimize Imports)快捷鍵,設置自己的喜好。
- 編輯完 .java、.kt、.xml 等文件后必須格式化(需要在設置好以下幾點的前提下)
Reformat Code 的必要性,一定需要保證 IDE 配置一致為前提,盡可能貼切于 Android Studio 默認。
強烈建議對于比較長的老代碼局部格式化,不全局格式化
-
每行字符數不得超過 160 字符,設置 Editor -> Code Style
-
全部設置為單路徑引用,
kotlinx.android.synthetic.main
除外。
Java Code Style
以上幾處設置完畢,其他采用 Android Studio 默認方式,再進行 Reformat Code 快捷鍵即可。
2. Android 的分包規范
前面強調了工具的統一配置,再利用 Android Studio 本身的功能便可把代碼風格變得一致。接下來就帶來第二部分:Android 的分包規范。
對于分包,我們需要達成一致,我們采用 PBF 方式,不推薦使用 PBL 方式。
PBF(按功能分包 Package By Feature)
PBL(按層分包 Package By Layer)
PBF 可能不是很好區分在哪個功能中,不過也比 PBL 要好找很多,且 PBF 與 PBL 相比較有如下優勢:
package 內高內聚,package 間低耦合
哪塊要添新功能,只改某一個 package 下的東西,而PBL 需要改多個 package,非常麻煩。package 有私有作用域(package-private scope)
原則上一個 package 下的不允許其他類訪問都是不應該加上 public 的。很容易刪除功能
統計發現新功能沒人用,這個版本那塊功能得去掉。如果是 PBL,得從功能入口到整個業務流程把受到牽連的所有能刪的代碼和 class 都揪出來刪掉,一不小心就完蛋。如果是 PBF,好說,先刪掉對應包,再刪掉功能入口(刪掉包后入口肯定報錯了),完事。高度抽象
解決問題的一般方法是從抽象到具體,PBF 包名是對功能模塊的抽象,包內的 class 是實現細節,符合從抽象到具體,而 PBL 弄反了。PBF 從確定 AppName 開始,根據功能模塊劃分 package,再考慮每塊的具體實現細節,而 PBL 從一開始就要考慮要不要 dao 層,要不要 com 層等等。只通過 class 來分離邏輯代碼
PBL 既分離 class 又分離 package,而 PBF 只通過 class 來分離邏輯代碼。package 的大小有意義了
PBL 中包的大小無限增長是合理的,因為功能越添越多,而 PBF 中包太大(包里 class 太多)表示這塊需要重構(劃分子包)。
3. Android 的命名規范
代碼中的命名嚴禁使用拼音與英文混合的方式,更不允許直接使用中文的方式。正確的英文拼寫和語法可以讓閱讀者易于理解,避免歧義。
注意:即使純拼音命名方式也要避免采用。但國際通用的名稱,可視同英文,比如
toutiao
、douyin
等。
3.1 包名
Android 里面有 package 的概念,所以需要約定一下包名命名規范。
包名全部小寫,不允許出現中文、大寫字母或者下劃線,前面為子模塊命名,再根據 PBF 方式進行命名。
3.2 類名
類名都以 UpperCamelCase
風格編寫。
類名通常是名詞或名詞短語,接口名稱有時可能是形容詞或形容詞短語。現在還沒有特定的規則或行之有效的約定來命名注解類型。
名詞,采用大駝峰命名法,盡量避免縮寫,除非該縮寫是眾所周知的, 比如 HTML、URL,如果類名稱中包含單詞縮寫,則單詞縮寫的每個字母均應大寫。
類 | 描述 | 例如 |
---|---|---|
Activity 類 |
模塊名 + Activity
|
閃屏頁類 SplashActivity
|
Fragment 類 |
模塊名 + Fragment
|
主頁類 HomeFragment
|
Service 類 |
模塊名 + Service
|
時間服務 TimeService
|
BroadcastReceiver 類 |
功能名 + Receiver
|
推送接收 JPushReceiver
|
ContentProvider 類 |
功能名 + Provider
|
ShareProvider |
自定義 View | 功能名 + View/ViewGroup(組件名稱) | ShapeButton |
Dialog對話框 | 功能名+Dialog | ImagePickerDialog |
Adapter 類 |
模塊名 + Adapter
|
課程詳情適配器 LessonDetailAdapter
|
解析類 | 功能名 + Parser
|
首頁解析類 HomePosterParser
|
工具方法類 | 功能名 + Utils 或 Manager
|
線程池管理類:ThreadPoolManager 日志工具類: LogUtils (Logger 也可)打印工具類: PrinterUtils
|
數據庫類 | 功能名 + DBHelper
|
新聞數據庫:NewsDBHelper
|
自定義的共享基礎類 |
Base + 基礎 |
BaseActivity , BaseFragment
|
抽象類 |
Base / Abstract 開頭 |
AbstractLogin |
異常類 |
Exception 結尾 |
LoginException |
接口 |
able / ible 結尾 / I 開頭 |
Runnable , Accessible ,ILoginView
|
測試類的命名以它要測試的類的名稱開始,以 Test 結束。例如:HashTest
或 HashIntegrationTest
。
接口(interface):命名規則與類一樣采用大駝峰命名法,多以 able 或 ible 結尾,如 interface Runnable
、interface Accessible
。
注意:如果項目采用 MVP,所有 Model、View、Presenter 的接口都以 I 為前綴,不加后綴,其他的接口采用上述命名規則。
3.3 方法名
方法名都以 lowerCamelCase
風格編寫。
方法名通常是動詞或動詞短語。
方法 | 說明 |
---|---|
initXX() |
初始化相關方法,使用 init 為前綴標識,如初始化布局 initView()
|
isXX() , checkXX()
|
方法返回值為 boolean 型的請使用 is/check 為前綴標識 |
getXX() |
返回某個值的方法,使用 get 為前綴標識 |
setXX() |
設置某個屬性值 |
handleXX() , processXX()
|
對數據進行處理的方法 |
displayXX() , showXX()
|
彈出提示框和提示信息,使用 display/show 為前綴標識 |
updateXX() |
更新數據 |
saveXX() , insertXX()
|
保存或插入數據 |
resetXX() |
重置數據 |
clearXX() |
清除數據 |
removeXX() , deleteXX()
|
移除數據或者視圖等,如 removeView()
|
drawXX() |
繪制數據或效果相關的,使用 draw 前綴標識 |
3.4 變量命名
這里的變量為廣義的變量,包括了常量、局部變量、全局變量等,它們的基礎規則是:
- 類型需要是名詞 / 名詞短語;
- 采用
lowerCamelCase
風格;
在具體的變量命名時,會根據該變量的類型不同而附加額外的命名規則:
類型 | 說明 | 例如 |
---|---|---|
常量 | 大寫 & 下劃線隔開,Kotlin 一定要 const val |
const val TYPE_NORMAL = 1 static final TYPE_NORMAL = 1
|
臨時變量名 | 整型:i 、j 、k 、m 、n ,字符型一般用 c 、d 、e
|
for(int i = 0;i < len; i++) |
其他變量 |
lowerCamelCase 風格即可,私有變量也不要使用 m 開頭 |
private int tmp; |
Kotlin | 只讀變量使用 val ,可變變量使用 var ,盡可能使用 val
|
var tmp = 0 val defaultIndex = 0
|
3.5 資源命名
Android 的資源包括:
資源文件命名為全部小寫,采用下劃線命名法。
3.5.1 動畫資源文件(anim/ 和 animator/)
安卓主要包含屬性動畫和視圖動畫,其視圖動畫包括補間動畫和逐幀動畫。屬性動畫文件需要放在 res/animator/
目錄下,視圖動畫文件需放在 res/anim/
目錄下。命名規則:{模塊名_}邏輯名稱
。
說明:
{}
中的內容為可選,邏輯名稱
可由多個單詞加下劃線組成。例如:refresh_progress.xml
、market_cart_add.xml
、market_cart_remove.xml
。
如果是普通的補間動畫或者屬性動畫,可采用:動畫類型_方向
的命名方式。
例如:
名稱 | 說明 |
---|---|
fade_in |
淡入 |
fade_out |
淡出 |
push_down_in |
從下方推入 |
push_down_out |
從下方推出 |
push_left |
推向左方 |
slide_in_from_top |
從頭部滑動進入 |
zoom_enter |
變形進入 |
slide_in |
滑動進入 |
shrink_to_middle |
中間縮小 |
3.5.2 顏色資源文件(color/)
color/ 是專門用于存放顏色相關資源的文件夾。命名規則:類型{_模塊名}_邏輯名稱
。
說明:
{}
中的內容為可選。例如:sel_btn_font.xml
。
顏色資源也可以放于 res/drawable/
目錄,引用時則用 @drawable
來引用,但不推薦這么做,最好還是把兩者分開。
3.5.3 圖片資源文件(drawable/ 和 mipmap/)
res/drawable/
目錄下放的是位圖文件(.png、.9.png、.jpg、.gif)或編譯為可繪制對象資源子類型的 XML 文件,而 res/mipmap/
目錄下放的是不同密度的啟動圖標,所以 res/mipmap/
只用于存放啟動圖標,其余圖片資源文件都應該放到 res/drawable/
目錄下。
命名規則:類型{_模塊名}_邏輯名稱
、類型{_模塊名}_顏色
。
說明:
{}
中的內容為可選;類型
可以是可繪制對象資源類型,也可以是控件類型最后可加后綴_small
表示小圖,_big
表示大圖。
例如:
名稱 | 說明 |
---|---|
btn_main_about.png |
主頁關于按鍵 類型_模塊名_邏輯名稱
|
btn_back.png |
返回按鍵 類型_邏輯名稱
|
divider_maket_white.png |
商城白色分割線 類型_模塊名_顏色
|
ic_edit.png |
編輯圖標 類型_邏輯名稱
|
bg_main.png |
主頁背景 類型_邏輯名稱
|
btn_red.png |
紅色按鍵 類型_顏色
|
btn_red_big.png |
紅色大按鍵 類型_顏色
|
ic_avatar_small.png |
小頭像圖標 類型_邏輯名稱
|
bg_input.png |
輸入框背景 類型_邏輯名稱
|
divider_white.png |
白色分割線 類型_顏色
|
bg_main_head.png |
主頁頭部背景 類型_模塊名_邏輯名稱
|
def_search_cell.png |
搜索頁面默認單元圖片 類型_模塊名_邏輯名稱
|
ic_more_help.png |
更多幫助圖標 類型_邏輯名稱
|
divider_list_line.png |
列表分割線 類型_邏輯名稱
|
sel_search_ok.xml |
搜索界面確認選擇器 類型_模塊名_邏輯名稱
|
shape_music_ring.xml |
音樂界面環形形狀 類型_模塊名_邏輯名稱
|
如果有多種形態,如按鈕選擇器:sel_btn_xx.xml
,采用如下命名:
名稱 | 說明 |
---|---|
sel_btn_xx |
作用在 btn_xx 上的 selector
|
btn_xx_normal |
默認狀態效果 |
btn_xx_pressed |
state_pressed 點擊效果 |
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,前提是命名要規范。
3.5.4 布局資源文件(layout/)
命名規則:類型_模塊名
、{模塊名_}類型_邏輯名稱
。(也采用 PBF,方便查看,尤其在大項目中)
說明:
{}
中的內容為可選。
例如:
類型 | 名稱 | 說明 |
---|---|---|
Activity |
main_activity.xml |
主窗體 模塊名_類型
|
Fragment |
music_fragment.xml |
音樂片段 模塊名_類型
|
Dialog |
loading_dialog.xml |
加載對話框 邏輯名稱_類型
|
PopupWindow |
info_ppw.xml |
信息彈窗(PopupWindow) 邏輯名稱_類型
|
adapter 的列表項 |
main_song_item.xml |
主頁歌曲列表項 模塊名_類型_邏輯名稱
|
3.5.5 布局資源 id 命名
命名規則:{模塊名_}_邏輯名_view 縮寫(功能)
,例如: main_search_btn
、back_btn
。此外,采用 Kotlinx 直接獲取布局文件的時候,id 命名采用駝峰樣式。
說明:
{}
中的內容為可選。參考 GoogleSamples Demo:https://github.com/android/architecture-samples
例如:
類型 | 規范 | 命名示例 |
---|---|---|
TextView |
xxx_text |
user_login_text |
EditText |
xxx_edit |
user_login_edit |
ImageView |
xxx_iv |
user_login_iv |
Button |
xxx_btn |
user_login_btn |
CheckBox |
xxx_cb |
user_login_cb |
GridView |
xxx_gv |
user_login_gv |
ListView |
xxx_lv |
user_login_lv |
RecyclerView |
xxx_rv |
user_login_rv |
RadioButton |
xxx_rb |
user_login_rb |
LinearLayout |
xxx_ll |
user_login_ll |
RelativeLayout |
xxx_rl |
user_login_rl |
FrameLayout |
xxx_fl |
user_login_fl |
GridLayout |
xxx_gl |
user_login_gl |
ConstraintLayout |
xxx_cl |
user_login_cl |
3.5.6 菜單資源文件(menu/)
菜單相關的資源文件應放在該目錄下。命名規則:{模塊名_}邏輯名稱
說明:
{}
中的內容為可選。例如:main_drawer.xml
、navigation.xml
。
3.5.7 colors.xml
<color>
的 name
命名使用下劃線命名法,在你的 colors.xml
文件中應該只是映射顏色的名稱一個 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>
使用這種格式,會非常容易重復定義 ARGB 值,而且如果應用要改變基色的話會非常困難。同時,這些定義是跟一些環境關聯起來的,如 button
或者 comment
,應該放到一個按鈕風格中,而不是在 colors.xml
文件中。
相反,應該這樣做:
<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>
向應用設計者那里要這個調色板,名稱不需要跟 "green"
、"blue"
等等相同。"brand_primary"
、"brand_secondary"
、"brand_negative"
這樣的名字也是完全可以接受的。像這樣規范的顏色很容易修改或重構,會使應用一共使用了多少種不同的顏色變得非常清晰。通常一個具有審美價值的 UI 來說,減少使用顏色的種類是非常重要的。
注意:如果某些顏色和主題有關,那就單獨寫一個
colors_theme.xml
。
3.5.8 strings.xml
<string>
的 name
命名使用下劃線命名法,采用以下規則:{模塊名_}邏輯名稱
,這樣方便同一個界面的所有 string
都放到一起,方便查找。
名稱 | 說明 |
---|---|
main_menu_about |
主菜單按鍵文字 |
friend_title |
好友模塊標題欄 |
friend_dialog_del |
好友刪除提示 |
login_check_email |
登錄驗證 |
dialog_title |
彈出框標題 |
button_ok |
確認鍵 |
loading |
加載文字 |
3.5.9 styles.xml
<style>
的 name
命名使用大駝峰命名法,幾乎每個項目都需要適當的使用 styles.xml
文件,因為對于一個視圖來說,有一個重復的外觀是很常見的,將所有的外觀細節屬性(colors
、padding
、font
)放在 styles.xml
文件中。 在應用中對于大多數文本內容,最起碼你應該有一個通用的 styles.xml
文件,例如:
<style name="ContentText">
<item name="android:textSize">@dimen/font_normal</item>
<item name="android:textColor">@color/basic_black</item>
</style>
應用到 TextView
中:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/price"
style="@style/ContentText"/>
或許你需要為按鈕控件做同樣的事情,不要停止在那里,將一組相關的和重復 android:xxxx
的屬性放到一個通用的 <style>
中。
4. Android 的注釋規范
4.1 類注釋
每個類完成后應該有作者姓名和聯系方式的注釋,對自己的代碼負責。
/**
* <pre>
* author : nanchen
* e-mail : xxx@xx
* time : 2021/01/18
* desc : xxxx 描述
* version: 1.0
* </pre>
*/
public class WelcomeActivity {
...
}
具體可以在 AS 中自己配制,進入 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>
*/
這樣便可在每次新建類的時候自動加上該頭注釋。
4.2 方法注釋
每一個成員方法(包括自定義成員方法、覆蓋方法、屬性方法)的方法頭都必須做方法頭注釋,在方法前一行輸入 /** + 回車
或者設置 Fix doc comment
(Settings -> Keymap -> Fix doc comment)快捷鍵,AS 便會幫你生成模板,我們只需要補全參數即可,如下所示。@param
, @return
, @throws
, @deprecated
這 4 種標記出現的時候,描述都不能為空。當描述無法在一行中容納,連續行至少需要再縮進 4 個空格。
/**
* Report an accessibility action to this view's parents for delegated processing.
*
* <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
* call this method to delegate an accessibility action to a supporting parent. If the parent
* returns true from its
* {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
* method this method will return true to signify that the action was consumed.</p>
*
* <p>This method is useful for implementing nested scrolling child views. If
* {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
* a custom view implementation may invoke this method to allow a parent to consume the
* scroll first. If this method returns true the custom view should skip its own scrolling
* behavior.</p>
*
* @param action Accessibility action to delegate
* @param arguments Optional action arguments
* @return true if the action was consumed by a parent
*/
public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
for (ViewParent p = getParent(); p != null; p = p.getParent()) {
if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
return true;
}
}
return false;
}
4.3 塊注釋
塊注釋與其周圍的代碼在同一縮進級別。它們可以是 /* ... */
風格,也可以是 // ...
風格(//
后最好帶一個空格)。對于多行的 /* ... */
注釋,后續行必須從 *
開始, 并且與前一行的 *
對齊。以下示例注釋都是 OK 的。
/*
* This is okay.
*/
// And so
// is this.
/* Or you can
* even do this. */
注釋不要封閉在由星號或其它字符繪制的框架里。
Tip:在寫多行注釋時,如果你希望在必要時能重新換行(即注釋像段落風格一樣),那么使用
/* ... */
。
比如:
4.4 全局變量的注釋
全局變量的注釋樣式如下(注意注釋之間有空格):
/**
* The next available accessibility id.
*/
private static int nextAccessibilityViewId;
/**
* The animation currently associated with this view.
*/
protected Animation currentAnimation = null;
4.5 其他一些注釋
AS 已幫你集成了一些注釋模板,我們只需要直接使用即可,在代碼中輸入 TODO
、FIXME
等這些注釋模板,回車后便會出現如下注釋。
// TODO: 17/3/14 需要實現,但目前還未實現的功能的說明
// FIXME: 17/3/14 需要修正,甚至代碼是錯誤的,不能工作,需要修復的說明
4.5 注釋必須遵守的規范
4.5.1 不言自明的方法不要加注釋。
比如 Item getItem(int index)
是一段自說明的代碼,我們可以直接從方法的命名就能知道它是干嘛的,所以不需要增加注釋。
4.5.2 提測的代碼不應該有 TODO 這樣的注釋
5. 代碼樣式規范
5.1 使用標準大括號樣式
左大括號不單獨占一行,與其前面的代碼位于同一行:
class MyClass {
int func() {
if (something) {
// ...
} else if (somethingElse) {
// ...
} else {
// ...
}
}
}
我們需要在條件語句周圍添加大括號。例外情況:如果整個條件語句(條件和主體)適合放在同一行,那么您可以(但不是必須)將其全部放在一行上。例如,我們接受以下樣式:
if (condition) {
body();
}
同樣也接受以下樣式:
if (condition) body();
但不接受以下樣式:
if (condition)
body(); // bad!
5.2 編寫簡短方法
在可行的情況下,盡量編寫短小精煉的方法。我們了解,有些情況下較長的方法是恰當的,因此對方法的代碼長度沒有做出硬性限制。如果某個方法的代碼超出 40 行,請考慮是否可以在不破壞程序結構的前提下對其拆解。
5.3 類成員的順序
這并沒有唯一的正確解決方案,但如果都使用一致的順序將會提高代碼的可讀性,推薦使用如下排序:
- 常量(Kotlin 伴生對象放在開頭)
- 字段
- 構造函數
- 重寫函數和回調
- 公有函數
- 私有函數
- 內部類或接口
例如:
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 組件(例如 Activity
或 Fragment
),那么把重寫函數按照他們的生命周期進行排序是一個非常好的習慣,例如,Activity
實現了 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() {}
}
5.4 函數參數的排序
在 Android 開發過程中,Context
在函數參數中是再常見不過的了,我們最好把 Context
作為其第一個參數。
正相反,我們把回調接口應該作為其最后一個參數。
例如:
// Context always goes first
public User loadUser(Context context, int userId);
// Callbacks always go last
public void loadUserAsync(Context context, int userId, UserCallback callback);
5.5 字符串常量的命名和值
Android SDK 中的很多類都用到了鍵值對函數,比如 SharedPreferences
、Bundle
、Intent
,所以,即便是一個小應用,我們最終也不得不編寫大量的字符串常量。
當時用到這些類的時候,我們 必須 將它們的鍵定義為 static final
字段,并遵循以下指示作為前綴。
類 | 字段名前綴 |
---|---|
SharedPreferences | PREF_ |
Bundle | BUNDLE_ |
Fragment Arguments | ARGUMENT_ |
Intent Extra | EXTRA_ |
Intent Action | ACTION_ |
說明:雖然 Fragment.getArguments()
得到的也是 Bundle
,但因為這是 Bundle
的常用用法,所以特意為此定義一個不同的前綴。
例如:
// 注意:字段的值與名稱相同以避免重復問題
static final String PREF_EMAIL = "PREF_EMAIL";
static final String BUNDLE_AGE = "BUNDLE_AGE";
static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID";
// 與意圖相關的項使用完整的包名作為值的前綴
static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME";
static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER";
5.6 行長限制
代碼中每一行文本的長度都應該不超過 160 個字符。雖然關于此規則存在很多爭論,但最終決定仍是以 160 個字符為上限,如果行長超過了 160(AS 窗口右側的豎線就是設置的行寬末尾 ),我們通常有兩種方法來縮減行長。
- 提取一個局部變量或方法(最好)。
- 使用換行符將一行換成多行。
不過存在以下例外情況:
- 如果備注行包含長度超過 160 個字符的示例命令或文字網址,那么為了便于剪切和粘貼,該行可以超過 160 個字符。
- 導入語句行可以超出此限制,因為用戶很少會看到它們(這也簡化了工具編寫流程)。
5.6.1 換行策略
這沒有一個準確的解決方案來決定如何換行,通常不同的解決方案都是有效的,但是有一些規則可以應用于常見的情況。
5.6.1.1 操作符的換行
除賦值操作符之外,我們把換行符放在操作符之前,例如:
int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne
+ theFinalOne;
賦值操作符的換行我們放在其后,例如:
int longName =
anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne;
5.6.1.2 函數鏈的換行
當同一行中調用多個函數時(比如使用構建器時),對每個函數的調用應該在新的一行中,我們把換行符插入在 .
之前。
例如:
Picasso.with(context).load("https://blankj.com/images/avatar.jpg").into(ivAvatar);
我們應該使用如下規則:
Picasso.with(context)
.load("https://blankj.com/images/avatar.jpg")
.into(ivAvatar);
5.6.1.3 多參數的換行
當一個方法有很多參數或者參數很長的時候,我們應該在每個 ,
后面進行換行。
比如:
loadPicture(context, "https://blankj.com/images/avatar.jpg", ivAvatar, "Avatar of the user", clickListener);
我們應該使用如下規則:
loadPicture(context,
"https://blankj.com/images/avatar.jpg",
ivAvatar,
"Avatar of the user",
clickListener);
5.6.1.4 RxJava 鏈式的換行
RxJava 的每個操作符都需要換新行,并且把換行符插入在 .
之前。
例如:
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;
}
});
}
參考文檔:
https://source.android.com/source/code-style?hl=zh-cn
https://developer.android.com/kotlin/style-guide?hl=zh-cn
https://github.com/Blankj/AndroidStandardDevelop