敲黑板一編程規范很重要

文章來自https://github.com/Blankj/AndroidStandardDevelop#
安卓開發規范(updating)

摘要

1 前言
2 AS規范
3 命名規范
4 資源文件規范
5 版本統一規范
6 第三方庫規范
7 注釋規范
8 測試規范
9 RN規范
10 其他的一些規范

1 前言

為了利于項目維護以及規范開發,促進成員之間Code Review的效率,故提出以下開發規范,如有更好建議,歡迎到GitHub提issue,原文地址:安卓開發規范(updating)

2 AS規范

工欲善其事,必先利其器。
盡量使用最新版的IDE進行開發;
編碼格式統一為UTF-8;
編輯完.java
、 .xml
等文件后一定要格式化(基本格式方面使用 AS 默認模板即可);
刪除多余的import,減少警告出現,可利用AS的Optimize Imports
(Settings → Keymap → Optimize Imports)快捷鍵;
Android開發者工具可以參考這里~ Android開發者工具

3 命名規范

代碼中的命名嚴禁使用拼音與英文混合的方式,更不允許直接使用中文的方式。正確的英文拼寫和語法可以讓閱讀者易于理解,避免歧義。
注意:即使純拼音命名方式也要避免采用。但alibaba
、taobao
、youku
、hangzhou
等國際通用的名稱,可視同英文。

3.1 包名

包名全部小寫,連續的單詞只是簡單地連接起來,不使用下劃線,采用反域名命名規則,全部使用小寫字母。一級包名是頂級域名,通常為com
,edu
,gov
,net
,org
等,二級包名為公司名,三級包名根據應用進行命名,后面就是對包名的劃分了,關于包名的劃分,推薦使用按功能分,一開始我們也是按照層去分包的,很坑爹。按照功能分可能你不是很好區分在哪個功能中,不過也比你按照層區分要好找很多。具體可以參考這篇博文~ Package by features, not layers,當然,我們大谷歌也有相應的sample~ iosched,其結構如下所示,很值得學習。

java
└─com
    └─google
        └─samples
            └─apps
                └─iosched
                    │  AppApplication.java  定義Application類
                    │  Config.java          定義配置數據(常量)
                    │
                    ├─about
                    │      AboutActivity.java
                    │
                    ├─appwidget
                    │      ScheduleWidgetProvider.java
                    │      ScheduleWidgetRemoteViewsService.java
                    │
                    ├─debug
                    │  │  DebugAction.java
                    │  │  DebugActivity.java
                    │  │  DebugFragment.java
                    │  │
                    │  └─actions
                    │          DisplayUserDataDebugAction.java
                    │          ForceAppDataSyncNowAction.java
                    │          ForceSyncNowAction.java
                    │          ...
                    │
                    ├─explore
                    │  │  ExploreIOActivity.java
                    │  │  ExploreIOFragment.java
                    │  │  ExploreModel.java
                    │  │  ...
                    │  │
                    │  └─data
                    │          ItemGroup.java
                    │          LiveStreamData.java
                    │          MessageData.java
                    │          ...
                    │
                    ├─feedback
                    │      FeedbackApiHelper.java
                    │      FeedbackConstants.java
                    │      FeedbackHelper.java
                    │      ...
                    │
                    ├─framework
                    │      FragmentListener.java
                    │      LoaderIdlingResource.java
                    │      Model.java
                    │      ...定義interface并實現
                    │
                    ├─gcm
                    │  │  GCMCommand.java
                    │  │  GCMIntentService.java
                    │  │  GCMRedirectedBroadcastReceiver.java
                    │  │  ...
                    │  │
                    │  └─command
                    │          AnnouncementCommand.java
                    │          NotificationCommand.java
                    │          SyncCommand.java
                    │          ...
                    │
                    ├─io
                    │  │  BlocksHandler.java
                    │  │  HandlerException.java
                    │  │  HashtagsHandler.java
                    │  │  ...處理model
                    │  │
                    │  ├─map
                    │  │  └─model
                    │  │          MapData.java
                    │  │          Marker.java
                    │  │          Tile.java
                    │  │
                    │  └─model
                    │          Block.java
                    │          DataManifest.java
                    │          Hashtag.java
                    │          ...
                    │
                    ├─map
                    │  │  InlineInfoFragment.java
                    │  │  MapActivity.java
                    │  │  MapFragment.java
                    │  │  ...
                    │  │
                    │  └─util
                    │          CachedTileProvider.java
                    │          MarkerLoadingTask.java
                    │          MarkerModel.java
                    │          ...
                    │
                    ├─model
                    │      ScheduleHelper.java
                    │      ScheduleItem.java
                    │      ScheduleItemHelper.java
                    │      ...定義model以及實現model相關操作
                    │
                    ├─myschedule
                    │      MyScheduleActivity.java
                    │      MyScheduleAdapter.java
                    │      MyScheduleFragment.java
                    │      ...
                    │
                    ├─provider
                    │      ScheduleContract.java
                    │      ScheduleContractHelper.java
                    │      ScheduleDatabase.java
                    │      ...實現ContentProvider
                    │      (也在此處定義provider依賴的其它類,比如db操作)
                    │
                    ├─receiver
                    │      SessionAlarmReceiver.java
                    │
                    ├─service
                    │      DataBootstrapService.java
                    │      SessionAlarmService.java
                    │      SessionCalendarService.java
                    │
                    ├─session
                    │      SessionDetailActivity.java
                    │      SessionDetailConstants.java
                    │      SessionDetailFragment.java
                    │      ...
                    │
                    ├─settings
                    │      ConfMessageCardUtils.java
                    │      SettingsActivity.java
                    │      SettingsUtils.java
                    │
                    ├─social
                    │      SocialActivity.java
                    │      SocialFragment.java
                    │      SocialModel.java
                    │
                    ├─sync
                    │  │  ConferenceDataHandler.java
                    │  │  RemoteConferenceDataFetcher.java
                    │  │  SyncAdapter.java
                    │  │  ...
                    │  │
                    │  └─userdata
                    │      │  AbstractUserDataSyncHelper.java
                    │      │  OnSuccessListener.java
                    │      │  UserAction.java
                    │      │  ...
                    │      │
                    │      ├─gms
                    │      │      DriveHelper.java
                    │      │      GMSUserDataSyncHelper.java
                    │      │
                    │      └─util
                    │              UserActionHelper.java
                    │              UserDataHelper.java
                    │
                    ├─ui
                    │  │  BaseActivity.java
                    │  │  CheckableLinearLayout.java
                    │  │  SearchActivity.java
                    │  │  ...BaseActivity以及自定義UI組件
                    │  │
                    │  └─widget
                    │          AspectRatioView.java
                    │          BakedBezierInterpolator.java
                    │          BezelImageView.java
                    │          ...自定義小UI控件
                    │
                    ├─util
                    │      AboutUtils.java
                    │      AccountUtils.java
                    │      AnalyticsHelper.java
                    │      ...工具類,提供靜態方法
                    │
                    ├─videolibrary
                    │      VideoLibraryActivity.java
                    │      VideoLibraryFilteredActivity.java
                    │      VideoLibraryFilteredFragment.java
                    │      ...
                    │
                    └─welcome
                            AccountFragment.java
                            AttendingFragment.java
                            ConductFragment.java
                            ...

參考Google I/O 2015的代碼結構,按功能分包具體可以這樣做:

src
└─com
    └─domain
        └─app
            │  AppApplication.java  定義Application類
            │  Config.java          定義配置數據(常量)
            │
            ├─framework
            │      定義interface以及相關基類
            │
            ├─io
            │      數據定義(model)、數據操作(比如json解析,但不包括db操作)
            │
            ├─model
            │      定義model(數據結構以及getter/setter、compareTo、equals等等,不含復雜操作)
            │      以及modelHelper(提供便于操作model的api)
            │
            ├─provider
            │      實現ContentProvider,及其依賴的db操作
            │
            ├─receiver
            │      實現Receiver
            │
            ├─service
            │      實現Service(比如IntentService),用于在獨立線程中異步do stuff
            │
            ├─ui
            │      實現BaseActivity,以及自定義view和widget,相關的Adapter也放這里
            │
            ├─util
            │      實現工具類,提供靜態方法
            │
            ├─feature1
            │      Item.java                定義model
            │      ItemHelper.java          實現modelHelper
            │      feature1Activity.java    定義UI
            │      feature1DAO.java         私有db操作
            │      feature1Utils.java       私有工具函數
            │      ...其它私有class
            │
            ├─...其它feature
  • PBF(按功能分包Package By Feature)與PBL(按層分包Package By Layer)相比較有如下優勢:
    package內高內聚,package間低耦合

  • 哪塊要添新功能,只改某一個package下的東西
    按class職能分層(PBL)降低了代碼耦合,但帶來了package耦合,要添新功能,需要改model、dbHelper、view、service等等,需要改動好幾個package下的代碼,改動的地方越多,越容易產生新問題,不是嗎?

  • 按功能分包(PBF),featureA相關的所有東西都在featureA包,feature內高內聚高度模塊化,不同feature之間低耦合,相關的東西都放在一起,還好找
    package有私有作用域(package-private scope)

  • 你負責開發這塊功能,這個目錄下所有東西都是你的
    PBL的方式是把所有工具方法都放在util包下,小張開發新功能時候發現需要一個xxUtil,但它又不是通用的,那應該放在哪里?沒辦法,按照分層原則,我們還得放在util包下,好像不太合適,但放在其它包更不合適,功能越來越多,util類也越定義越多。后來小李負責開發一塊功能時發現需要一個xxUtil,同樣不通用,去util包一看,怎么已經有了,而且還沒法復用,只好放棄xx這個名字,改為xxxUtil……因為PBL的package沒有私有作用域,每一個包都是public(跨包方法調用是很平常的事情,每一個包對其它包來說都是可訪問的)

  • 如果是PBF,小張的xxUtil自然放在feautreA下,小李的xxUtil在featureB下,如果覺得util好像是通用的,就去util包看看要不要把工具方法添進xxUtil,class命名沖突沒有了
    PBF的package有私有作用域,featureA不應該訪問featureB下的任何東西(如果非訪問不可,那就說明接口定義有問題)
    很容易刪除功能

  • 統計發現新功能沒人用,這個版本那塊功能得去掉
    如果是PBL,得從功能入口到整個業務流程把受到牽連的所有能刪的代碼和class都揪出來刪掉,一不小心就完蛋
    如果是PBF,好說,先刪掉對應包,再刪掉功能入口(刪掉包后入口肯定報錯了),完事
    高度抽象

  • 解決問題的一般方法是從抽象到具體,PBF包名是對功能模塊的抽象,包內的class是實現細節,符合從抽象到具體,而PBL弄反了
    PBF從確定AppName開始,根據功能模塊劃分package,再考慮每塊的具體實現細節,而PBL從一開始就要考慮要不要dao層,要不要com層等等
    只通過class來分離邏輯代碼

  • PBL既分離class又分離package,而PBF只通過class來分離邏輯代碼
    沒有必要通過package分離,因為PBL中也可能出現尷尬的情況:

├─service
        │      MainServ.java
  • 按照PBL,service包下的所有東西都是Controller,應該不需要Serv后綴,但實際上通常為了碼起來方便,直接import service包,Serv后綴是為了避免引入的class和當前包下的class命名沖突,當然,不用后綴也可以,得寫清楚包路徑,比如new net.ayqy.service.Main(),麻煩
    而PBF就很方便,無需import,直接new MainServ()即可
    package的大小有意義了

  • PBL中包的大小無限增長是合理的,因為功能越添越多
    而PBF中包太大(包里class太多)表示這塊需要重構(劃分子包)

3.2 類名

類名都以UpperCamelCase
風格編寫。
類名通常是名詞或名詞短語,接口名稱有時可能是形容詞或形容詞短語?,F在還沒有特定的規則或行之有效的約定來命名注解類型。
名詞,采用大駝峰命名法,盡量避免縮寫,除非該縮寫是眾所周知的, 比如HTML
, URL
,如果類名稱中包含單詞縮寫,則單詞縮寫的每個字母均應大寫。


  • 描述
    例如

  • Activity 類
    Activity為后綴標識
    歡迎頁面類WelcomeActivity

  • Adapter類
    Adapter 為后綴標識
    新聞詳情適配器 NewDetailAdapter

  • 解析類
    Parser為后綴標識
    首頁解析類HomePosterParser

  • 工具方法類
    Utils或Manager為后綴標識(與系統或第三方的Utils區分)或功能+Utils
    線程池管理類:ThreadPoolManager日志工具類:LogUtils(Logger也可)打印工具類:PrinterUtils

  • 數據庫類
    以DBHelper后綴標識
    新聞數據庫:NewDBHelper

  • Service類
    以Service為后綴標識
    時間服務TimeService

  • BroadcastReceiver類
    以Receiver為后綴標識
    推送接收JPushReceiver

  • ContentProvider類
    以Provider為后綴標識
    ShareProvider

  • 自定義的共享基礎類
    以Base開頭
    BaseActivity,BaseFragment

  • 測試類的命名以它要測試的類的名稱開始,以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()
    保存數據

  • resetXX()
    重置數據

  • clearXX()
    清除數據

  • removeXX()
    移除數據或者視圖等,如removeView();

  • drawXX()
    繪制數據或效果相關的,使用draw前綴標識

3.4 常量名

常量名命名模式為CONSTANT_CASE
,全部字母大寫,用下劃線分隔單詞。那,到底什么算是一個常量?
每個常量都是一個靜態final
字段,但不是所有靜態final
字段都是常量。在決定一個字段是否是一個常量時,考慮它是否真的感覺像是一個常量。例如,如果任何一個該實例的觀測狀態是可變的,則它幾乎肯定不會是一個常量。只是永遠不打算改變對象一般是不夠的,它要真的一直不變才能將它示為常量。

// Constants
static final int NUMBER = 5;
static final ImmutableListNAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(','); // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }

// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final SetmutableCollection = new HashSet();
static final ImmutableSetmutableElements = ImmutableSet.of(mutable);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};

3.5 非常量字段名

非常量字段名以lowerCamelCase
風格的基礎上改造為如下風格:基本結構為scopeVariableNameType
。
scope:范圍
非公有,非靜態字段命名以m開頭。
靜態字段命名以s開頭。
公有非靜態字段命名以p開頭。
公有靜態字段(全局變量)命名以g開頭。
例子:

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

使用1字符前綴來表示作用范圍,1個字符的前綴必須小寫,前綴后面是由表意性強的一個單詞或多個單詞組成的名字,而且每個單詞的首寫字母大寫,其它字母小寫,這樣保證了對變量名能夠進行正確的斷句。
Type:類型
考慮到Android中使用很多UI控件,為避免控件和普通成員變量混淆以及更好達意,所有用來表示控件的成員變量統一加上控件縮寫作為后綴(文末附有縮寫表)。
對于普通變量一般不添加類型后綴,如果統一添加類型后綴,請參考文末的縮寫表。
用統一的量詞通過在結尾處放置一個量詞,就可創建更加統一的變量,它們更容易理解,也更容易搜索。
注意:如果項目中使用ButterKnife
,則不添加m前綴,以lowerCamelCase
風格命名。

例如,請使用mCustomerStrFirst
和mCustomerStrLast
,而不要使用mFirstCustomerStr
和mLastCustomerStr
。
量詞列表
量詞后綴說明

First
一組變量中的第一個

Last
一組變量中的最后一個

Next
一組變量中的下一個變量

Prev
一組變量中的上一個

Cur
一組變量中的當前變量

說明:
集合添加如下后綴:List、Map、Set 數組添加如下后綴:Arr
注意:所有的VO(值對象)統一采用標準的lowerCamelCase風格編寫,所有的DTO(數據傳輸對象)就按照接口文檔中定義的字段名編寫。

3.6 參數名

參數名以lowerCamelCase
風格編寫。 參數應該避免用單個字符命名。

3.7 局部變量名

局部變量名以lowerCamelCase
風格編寫,比起其它類型的名稱,局部變量名可以有更為寬松的縮寫。
雖然縮寫更寬松,但還是要避免用單字符進行命名,除了臨時變量和循環變量。
即使局部變量是final和不可改變的,也不應該把它示為常量,自然也不能用常量的規則去命名它。

3.8 臨時變量

臨時變量通常被取名為i
、j
、k
、m
和n
,它們一般用于整型;c
、d
、e
,它們一般用于字符型。 如:for (int i = 0; i < len ; i++)
。

3.9 類型變量名

類型變量可用以下兩種風格之一進行命名:
單個的大寫字母,后面可以跟一個數字(如:E
, T
, X
, T2
)。
以類命名方式(參考3.2 類名),后面加個大寫的T
(如:RequestT
, FooBarT
)。

更多還可參考~ 阿里巴巴Java開發手冊

4 資源文件規范

4.1 資源布局文件(XML文件(layout布局文件))

全部小寫,采用下劃線命名法

4.1.1 contentView命名

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

4.1.2 Dialog命名

規則:dialog_描述.xml

例如:dialog_hint.xml

4.1.3 PopupWindow命名

規則:ppw_描述.xml

例如:ppw_info.xml

4.1.4 列表項命名

規則:item_描述.xml

例如:item_city.xml

4.1.5 包含項命名

規則:模塊_(位置)描述.xml

例如:activity_main_head.xml
、activity_main_bottom.xml

注意:通用的包含項命名采用:項目名稱縮寫_描述.xml

例如:xxxx_title.xml

4.2 資源文件(圖片drawable文件夾下)

全部小寫,采用下劃線命名法,加前綴區分
命名模式:可加后綴 small
表示小圖, big
表示大圖,邏輯名稱可由多個單詞加下劃線組成,采用以下規則:
用途
模塊名
邏輯名稱

用途模塊名顏色

用途_邏輯名稱

用途_顏色

說明:用途也指控件類型(具體見附錄UI控件縮寫表
例如:
名稱
說明

btn_main_home.png
按鍵用途模塊名邏輯名稱

divider_maket_white.png
分割線用途模塊名顏色

ic_edit.png
圖標用途_邏輯名稱

bg_main.png
背景用途_邏輯名稱

btn_red.png
紅色按鍵用途_顏色

btn_red_big.png
紅色大按鍵用途_顏色

ic_head_small.png
小頭像用途_邏輯名稱

bg_input.png
輸入框背景用途_邏輯名稱

divider_white.png
白色分割線用途_顏色

bg_main_head
主模塊頭部背景圖片用途模塊名邏輯名稱

def_search_cell
默認搜索界面單元圖片用途模塊名邏輯名稱

ic_more_help
更多幫助圖標用途_邏輯名稱

divider_list_line
列表分割線用途_邏輯名稱

sel_search_ok
搜索界面確認選擇器用途模塊名邏輯名稱

shape_music_ring
音樂界面環形形狀用途模塊名邏輯名稱

如果有多種形態,如按鈕選擇器:sel_btn_xx.xml

名稱
說明

sel_btn_xx
按鈕圖片使用btn_整體效果
(selector)

btn_xx_normal
按鈕圖片使用btn_正常情況效果

btn_xx_pressed
按鈕圖片使用btn_點擊時候效果

btn_xx_focused
state_focused
聚焦效果

btn_xx_disabled
state_enabled
(false)不可用效果

btn_xx_checked
state_checked
選中效果

btn_xx_selected
state_selected
選中效果

btn_xx_hovered
state_hovered
懸停效果

btn_xx_checkable
state_checkable
可選效果

btn_xx_activated
state_activated
激活的

btn_xx_windowfocused
state_window_focused

注意:使用AndroidStudio的插件SelectorChapek
可以快速生成selector,前提是命名要規范。

4.3 動畫文件(anim文件夾下)

全部小寫,采用下劃線命名法,加前綴區分。
具體動畫采用以下規則:模塊名邏輯名稱
。
例如:refresh_progress.xml
、market_cart_add.xml
、market_cart_remove.xml

普通的tween動畫采用如下表格中的命名方式:動畫類型
方向

名稱
說明

fade_in
淡入

fade_out
淡出

push_down_in
從下方推入

push_down_out
從下方推出

push_left
推向左方

slide_in_from_top
從頭部滑動進入

zoom_enter
變形進入

slide_in
滑動進入

shrink_to_middle
中間縮小

4.4 values中name命名

4.4.1 colors.xml

colors.xml
的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
。

4.4.2 dimens.xml

像對待colors.xml
一樣對待dimens.xml
文件 與定義顏色調色板一樣,你同時也應該定義一個空隙間隔和字體大小的“調色板”。 一個好的例子,如下所示:

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

布局時在寫margins
和paddings
時,你應該使用spacing_xx
尺寸格式來布局,而不是像對待string
字符串一樣直接寫值,像這樣規范的尺寸很容易修改或重構,會使應用所有用到的尺寸一目了然。 這樣寫會非常有感覺,會使組織和改變風格或布局是非常容易。

4.4.3 strings.xml

strings
的name
命名使用下劃線命名法,采用以下規則:模塊名+邏輯名稱
,這樣方便同一個界面的所有string都放到一起,方便查找。
名稱
說明

main_menu_about
主菜單按鍵文字

friend_title
好友模塊標題欄

friend_dialog_del
好友刪除提示

login_check_email
登錄驗證

dialog_title
彈出框標題

button_ok
確認鍵

loading
加載文字

4.4.4 styles.xml

style
的name
命名使用大駝峰命名法,幾乎每個項目都需要適當的使用style
文件,因為對于一個視圖來說有一個重復的外觀是很常見的,將所有的外觀細節屬性(colors
、padding
、font
)放在style
文件中。 在應用中對于大多數文本內容,最起碼你應該有一個通用的style
文件,例如:
<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:****
的屬性放到一個通用的style
中。
將一個大的styles.xml
文件分割成多個文件
, 你可以有多個styles.xml
文件。Android SDK支持其它文件,styles.xml
這個文件名稱并沒有作用,起作用的是在文件里的<style>
標簽。因此你可以有多個style文件,如styles.xml
、styles_home.xml
、styles_item_details.xml
、styles_forms.xml
。 不同于資源文件路徑需要為系統構建起的有意義,在res/values
目錄下的文件可以任意命名。

4.5 layout中的id命名

命名模式為:view縮寫模塊名邏輯名
,比如btn_main_search
使用AndroidStudio
的插件ButterKnife Zelezny
,生成注解非常方便,原生的話可以使用Android Code Generator
插件。
如果想對資源文件進行分包可以參考我這篇文章~ Android Studio下對資源進行分包

5 版本統一規范

Android開發存在著眾多版本的不同,比如compileSdkVersion
、minSdkVersion
、targetSdkVersion
以及項目中依賴第三方庫的版本,不同的module及不同的開發人員都有不同的版本,所以需要一個統一版本規范的文件。
具體可以參考我寫的這篇博文~ Android開發之版本統一規范

6 第三方庫規范

別再閉門造車了,用用最新最火的技術吧,安利一波~ Android 流行框架查速表,順便帶上自己的干貨~ Android開發人員不得不收集的代碼
希望Team能用時下較新的技術,對開源庫的選取,一般都需要選擇比較穩定的版本,作者在維護的項目,要考慮作者對issue的解決,以及開發者的知名度等各方面。選取之后,一定的封裝是必要的。
個人推薦Team可使用如下優秀輪子:
Retrofit
RxAndroid
OkHttp
Glide / Fresco
Gson / Fastjson
EventBus / AndroidEventBus
GreenDao
Dagger2(選用)
Tinker(選用)

7 注釋規范

為了減少他人閱讀你代碼的痛苦值,請在關鍵地方做好注釋。

7.1 類注釋

每個類完成后應該有作者姓名和聯系方式的注釋,對自己的代碼負責。
/** * <pre> * author : Blankj * e-mail : xxx@xx * time : 2017/03/07 * 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> */

這樣便可在每次新建類的時候自動加上該頭注釋。

7.2 方法注釋

每一個成員方法(包括自定義成員方法、覆蓋方法、屬性方法)的方法頭都必須做方法頭注釋,在方法前一行輸入/** + 回車
或者設置Fix doc comment
(Settings → Keymap → Fix doc comment)快捷鍵,AS便會幫你生成模板,我們只需要補全參數即可,如下所示。
/** * bitmap轉byteArr * * @param bitmap bitmap對象 * @param format 格式 * @return 字節數組 */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();}

7.3 塊注釋

塊注釋與其周圍的代碼在同一縮進級別。它們可以是/* ... /
風格,也可以是// ...
風格(
//
后最好帶一個空格
)。對于多行的/ ... /
注釋,后續行必須從

開始, 并且與前一行的*
對齊。以下示例注釋都是OK的。
/* * This is // And so /* Or you can * okay. // is this. * even do this. */ */

注釋不要封閉在由星號或其它字符繪制的框架里。
Tip:在寫多行注釋時,如果你希望在必要時能重新換行(即注釋像段落風格一樣),那么使用/* ... */
。

7.4 其他一些注釋

AS已幫你集成了一些注釋模板,我們只需要直接使用即可,在代碼中輸入todo
、fixme
等這些注釋模板,回車后便會出現如下注釋
// TODO: 17/3/14 需要實現,但目前還未實現的功能的說明// FIXME: 17/3/14 需要修正,甚至代碼是錯誤的,不能工作,需要修復的說明

8 測試規范

業務開發完成之后,開發人員做單元測試,單元測試完成之后,保證單元測試全部通過同時單元測試代碼覆蓋率達到一定程度(這個需要開發和測試約定,理論上越高越好),開發提測。
// TODO...

9 RN規范

// TODO...

10 其他的一些規范

合理布局,有效運用<merge>
、<ViewStub>
、<include>
標簽;

Activity
和Fragment
里面有許多重復的操作以及操作步驟,所以我們都需要提供一個BaseActivity
和BaseFragment
,讓所有的Activity
和Fragment
都繼承這個基類。

啟動Activity
的話建議使用AS自帶的模板,輸入starter
即可,如下所示:

public static void start(Context context, String data) { Intent starter = new Intent(context, MainActivity.class); starter.putExtra("data", data); context.startActivity(starter);}

同理,啟動Fragment
輸入newInstance
即可,如下所示:
public static MainFragment newInstance(String data) { Bundle args = new Bundle(); args.putString("data", data); MainFragment fragment = new MainFragment(); fragment.setArguments(args); return fragment;}

方法基本上都按照調用的先后順序在各自區塊中排列;

相關功能作為小區塊放在一起(或者封裝掉);

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

數據提供統一的入口。無論是在 MVP、MVC 還是 MVVM 中,提供一個統一的數據入口,都可以讓代碼變得更加易于維護。比如可使用一個DataManager
,把 http
、preference
、eventpost
、database
都放在DataManger
里面進行操作,我們只需要與DataManger
打交道;

多用組合, 少用繼承;

提取方法, 去除重復代碼。對于必要的工具類抽取也很重要,這在以后的項目中是可以重用的。

可引入 Dagger2 減少模塊之間的耦合性。Dagger2 是一個依賴注入框架,使用代碼自動生成創建依賴關系需要的代碼。減少很多模板化的代碼,更易于測試,降低耦合,創建可復用可互換的模塊;

項目引入RxJava

  • RxAndroid
    這些響應式編程,可以極大的減少邏輯代碼;

通過引入事件總線,如:EventBus
、AndroidEventBus
、RxBus
,它允許我們在DataLayer
中發送事件,以便ViewLayer
中的多個組件都能夠訂閱到這些事件,減少回調;

盡可能使用局部變量;

及時關閉流;

盡量減少對變量的重復計算;

如下面的操作:
for (int i = 0; i < list.size(); i++) { ...}

建議替換為:
for (int i = 0, len = list.size(); i < len; i++) { ...}

盡量采用懶加載的策略,即在需要的時候才創建;

例如:
String str = "aaa";if (i == 1) { list.add(str);}

建議替換為:
if (i == 1) { String str = "aaa"; list.add(str);}

不要在循環中使用try…catch…,應該把其放在最外層;

使用帶緩沖的輸入輸出流進行IO操作;

盡量使用HashMap、ArrayList、StringBuilder,除非線程安全需要,否則不推薦使用Hashtable、Vector、StringBuffer,后三者由于使用同步機制而導致了性能開銷;

盡量在合適的場合使用單例;

使用單例可以減輕加載的負擔、縮短加載的時間、提高加載的效率,但并不是所有地方都適用于單例,簡單來說,單例主要適用于以下三個方面:
(1)控制資源的使用,通過線程同步來控制資源的并發訪問
(2)控制實例的產生,以達到節約資源的目的
(3)控制數據的共享,在不建立直接關聯的條件下,讓多個不相關的進程或線程之間實現通信
把一個基本數據類型轉為字符串,基本數據類型.toString()
是最快的方式、String.valueOf(數據)
次之、數據 + ""
最慢;

使用AS自帶的Lint來優化代碼結構(什么,你不會?右鍵module、目錄或者文件,選擇Analyze → Inspect Code);

最后不要忘了內存泄漏的檢測;

最后啰嗦幾句:
好的命名規則能夠提高代碼質量,使得新人加入項目的時候降低理解代碼的難度;
規矩終究是死的,適合團隊的才是最好的;
命名規范需要團隊一起齊心協力來維護執行,在團隊生活里,誰都不可能獨善其身;
一開始可能會有些不習慣,持之以恒,總會成功的。


附錄

UI控件縮寫表

名稱
縮寫

TextView
tv

EditText
et

ImageButton
ib

Button
btn

ImageView
iv

ListView
lv

GridView
gv

ProgressBar
pb

SeekBar
sb

RadioButtion
rb

CheckBox
cb

ScrollView
sv

LinearLayout
ll

FrameLayout
fl

RelativeLayout
rl

RecyclerView
rv

WebView
wv

VideoView
vv

Spinner
spn

ToggleButton
tb

常見的英文單詞縮寫表

名稱
縮寫

icon
ic (主要用在app的圖標)

color
cl(主要用于顏色值)

average
avg

background
bg(主要用于布局和子布局的背景)

selector
sel主要用于某一view多種狀態,不僅包括Listview中的selector,還包括按鈕的selector)

buffer
buf

control
ctrl

default
def

delete
del

document
doc

error
err

escape
esc

increment
inc

infomation
info

initial
init

image
img

Internationalization
I18N

length
len

library
lib

message
msg

password
pwd

position
pos

server
srv

string
str

temp
tmp

window
wnd(win)

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

參考

Android包命名規范
Android 開發最佳實踐
Android 編碼規范
阿里巴巴Java開發手冊
Google Java編程風格指南
小細節,大用途,35 個 Java 代碼性能優化總結!

版本日志

17/03/06: 發布初版 ;
17/03/07: 修訂目錄排版,完善某些細節;
17/03/08: 規范排版,修復typor及新增一些規范;
17/03/13: 新增其他注釋;
17/03/14: 包名劃分為按功能劃分;

——powered by Blankj(蔡夢杰)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容

  • 請看完結版:Android開發規范(完結版)
    Blankj閱讀 8,624評論 25 115
  • 開發規范 首先,我這篇開發規范,只是針對于剛進入職場的萌新來寫的,已經形成自己開發風格的可以自行繞過。其次,這些也...
    手術刀切西瓜閱讀 868評論 0 6
  • Android編碼規范 源文件基礎 文件名 源文件以其最頂層的類名來命名,大小寫敏感,文件擴展名為.java。 文...
    呼呼哥閱讀 969評論 0 0
  • Android 編碼規范 1. 前言 這份文檔是 Google Java Code Style 的譯文,并稍有添加...
    人失憶閱讀 448評論 0 3
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139