文章來自https://github.com/Blankj/AndroidStandardDevelop#
安卓開發(fā)規(guī)范(updating)
摘要
1 前言
2 AS規(guī)范
3 命名規(guī)范
4 資源文件規(guī)范
5 版本統(tǒng)一規(guī)范
6 第三方庫規(guī)范
7 注釋規(guī)范
8 測(cè)試規(guī)范
9 RN規(guī)范
10 其他的一些規(guī)范
1 前言
為了利于項(xiàng)目維護(hù)以及規(guī)范開發(fā),促進(jìn)成員之間Code Review的效率勘伺,故提出以下開發(fā)規(guī)范,如有更好建議接剩,歡迎到GitHub提issue窟扑,原文地址:安卓開發(fā)規(guī)范(updating)
2 AS規(guī)范
工欲善其事蚯窥,必先利其器什乙。
盡量使用最新版的IDE進(jìn)行開發(fā)淋硝;
編碼格式統(tǒng)一為UTF-8制恍;
編輯完.java
父能、 .xml
等文件后一定要格式化(基本格式方面使用 AS 默認(rèn)模板即可);
刪除多余的import净神,減少警告出現(xiàn)何吝,可利用AS的Optimize Imports
(Settings → Keymap → Optimize Imports)快捷鍵;
Android開發(fā)者工具可以參考這里~ Android開發(fā)者工具
3 命名規(guī)范
代碼中的命名嚴(yán)禁使用拼音與英文混合的方式,更不允許直接使用中文的方式鹃唯。正確的英文拼寫和語法可以讓閱讀者易于理解,避免歧義爱榕。
注意:即使純拼音命名方式也要避免采用。但alibaba
坡慌、taobao
黔酥、youku
、hangzhou
等國際通用的名稱,可視同英文。
3.1 包名
包名全部小寫跪者,連續(xù)的單詞只是簡單地連接起來棵帽,不使用下劃線,采用反域名命名規(guī)則坑夯,全部使用小寫字母岖寞。一級(jí)包名是頂級(jí)域名,通常為com
,edu
,gov
,net
,org
等柜蜈,二級(jí)包名為公司名仗谆,三級(jí)包名根據(jù)應(yīng)用進(jìn)行命名,后面就是對(duì)包名的劃分了淑履,關(guān)于包名的劃分隶垮,推薦使用按功能分,一開始我們也是按照層去分包的秘噪,很坑爹狸吞。按照功能分可能你不是很好區(qū)分在哪個(gè)功能中,不過也比你按照層區(qū)分要好找很多指煎。具體可以參考這篇博文~ Package by features, not layers蹋偏,當(dāng)然,我們大谷歌也有相應(yīng)的sample~ iosched至壤,其結(jié)構(gòu)如下所示威始,很值得學(xué)習(xí)。
java
└─com
└─google
└─samples
└─apps
└─iosched
│ AppApplication.java 定義Application類
│ Config.java 定義配置數(shù)據(jù)(常量)
│
├─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并實(shí)現(xiàn)
│
├─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以及實(shí)現(xiàn)model相關(guān)操作
│
├─myschedule
│ MyScheduleActivity.java
│ MyScheduleAdapter.java
│ MyScheduleFragment.java
│ ...
│
├─provider
│ ScheduleContract.java
│ ScheduleContractHelper.java
│ ScheduleDatabase.java
│ ...實(shí)現(xiàn)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
│ ...工具類黎棠,提供靜態(tài)方法
│
├─videolibrary
│ VideoLibraryActivity.java
│ VideoLibraryFilteredActivity.java
│ VideoLibraryFilteredFragment.java
│ ...
│
└─welcome
AccountFragment.java
AttendingFragment.java
ConductFragment.java
...
參考Google I/O 2015的代碼結(jié)構(gòu),按功能分包具體可以這樣做:
src
└─com
└─domain
└─app
│ AppApplication.java 定義Application類
│ Config.java 定義配置數(shù)據(jù)(常量)
│
├─framework
│ 定義interface以及相關(guān)基類
│
├─io
│ 數(shù)據(jù)定義(model)镰绎、數(shù)據(jù)操作(比如json解析脓斩,但不包括db操作)
│
├─model
│ 定義model(數(shù)據(jù)結(jié)構(gòu)以及getter/setter、compareTo畴栖、equals等等随静,不含復(fù)雜操作)
│ 以及modelHelper(提供便于操作model的api)
│
├─provider
│ 實(shí)現(xiàn)ContentProvider,及其依賴的db操作
│
├─receiver
│ 實(shí)現(xiàn)Receiver
│
├─service
│ 實(shí)現(xiàn)Service(比如IntentService)吗讶,用于在獨(dú)立線程中異步do stuff
│
├─ui
│ 實(shí)現(xiàn)BaseActivity挪挤,以及自定義view和widget,相關(guān)的Adapter也放這里
│
├─util
│ 實(shí)現(xiàn)工具類关翎,提供靜態(tài)方法
│
├─feature1
│ Item.java 定義model
│ ItemHelper.java 實(shí)現(xiàn)modelHelper
│ feature1Activity.java 定義UI
│ feature1DAO.java 私有db操作
│ feature1Utils.java 私有工具函數(shù)
│ ...其它私有class
│
├─...其它feature
PBF(按功能分包Package By Feature)與PBL(按層分包Package By Layer)相比較有如下優(yōu)勢(shì):
package內(nèi)高內(nèi)聚扛门,package間低耦合哪塊要添新功能,只改某一個(gè)package下的東西
按class職能分層(PBL)降低了代碼耦合纵寝,但帶來了package耦合论寨,要添新功能星立,需要改model、dbHelper葬凳、view绰垂、service等等,需要改動(dòng)好幾個(gè)package下的代碼火焰,改動(dòng)的地方越多劲装,越容易產(chǎn)生新問題,不是嗎昌简?按功能分包(PBF)占业,featureA相關(guān)的所有東西都在featureA包,feature內(nèi)高內(nèi)聚高度模塊化纯赎,不同feature之間低耦合谦疾,相關(guān)的東西都放在一起,還好找
package有私有作用域(package-private scope)你負(fù)責(zé)開發(fā)這塊功能犬金,這個(gè)目錄下所有東西都是你的
PBL的方式是把所有工具方法都放在util包下念恍,小張開發(fā)新功能時(shí)候發(fā)現(xiàn)需要一個(gè)xxUtil,但它又不是通用的晚顷,那應(yīng)該放在哪里峰伙?沒辦法,按照分層原則该默,我們還得放在util包下瞳氓,好像不太合適,但放在其它包更不合適权均,功能越來越多,util類也越定義越多锅锨。后來小李負(fù)責(zé)開發(fā)一塊功能時(shí)發(fā)現(xiàn)需要一個(gè)xxUtil叽赊,同樣不通用,去util包一看必搞,怎么已經(jīng)有了必指,而且還沒法復(fù)用,只好放棄xx這個(gè)名字恕洲,改為xxxUtil……因?yàn)镻BL的package沒有私有作用域塔橡,每一個(gè)包都是public(跨包方法調(diào)用是很平常的事情,每一個(gè)包對(duì)其它包來說都是可訪問的)如果是PBF霜第,小張的xxUtil自然放在feautreA下葛家,小李的xxUtil在featureB下,如果覺得util好像是通用的泌类,就去util包看看要不要把工具方法添進(jìn)xxUtil癞谒,class命名沖突沒有了
PBF的package有私有作用域,featureA不應(yīng)該訪問featureB下的任何東西(如果非訪問不可,那就說明接口定義有問題)
很容易刪除功能統(tǒng)計(jì)發(fā)現(xiàn)新功能沒人用弹砚,這個(gè)版本那塊功能得去掉
如果是PBL双仍,得從功能入口到整個(gè)業(yè)務(wù)流程把受到牽連的所有能刪的代碼和class都揪出來刪掉,一不小心就完蛋
如果是PBF桌吃,好說朱沃,先刪掉對(duì)應(yīng)包,再刪掉功能入口(刪掉包后入口肯定報(bào)錯(cuò)了)茅诱,完事
高度抽象解決問題的一般方法是從抽象到具體逗物,PBF包名是對(duì)功能模塊的抽象,包內(nèi)的class是實(shí)現(xiàn)細(xì)節(jié)让簿,符合從抽象到具體敬察,而PBL弄反了
PBF從確定AppName開始,根據(jù)功能模塊劃分package尔当,再考慮每塊的具體實(shí)現(xiàn)細(xì)節(jié)莲祸,而PBL從一開始就要考慮要不要dao層,要不要com層等等
只通過class來分離邏輯代碼PBL既分離class又分離package椭迎,而PBF只通過class來分離邏輯代碼
沒有必要通過package分離锐帜,因?yàn)镻BL中也可能出現(xiàn)尷尬的情況:
├─service
│ MainServ.java
按照PBL,service包下的所有東西都是Controller畜号,應(yīng)該不需要Serv后綴缴阎,但實(shí)際上通常為了碼起來方便,直接import service包简软,Serv后綴是為了避免引入的class和當(dāng)前包下的class命名沖突蛮拔,當(dāng)然,不用后綴也可以痹升,得寫清楚包路徑建炫,比如new net.ayqy.service.Main(),麻煩
而PBF就很方便疼蛾,無需import肛跌,直接new MainServ()即可
package的大小有意義了PBL中包的大小無限增長是合理的,因?yàn)楣δ茉教碓蕉?br> 而PBF中包太大(包里class太多)表示這塊需要重構(gòu)(劃分子包)
3.2 類名
類名都以UpperCamelCase
風(fēng)格編寫察郁。
類名通常是名詞或名詞短語衍慎,接口名稱有時(shí)可能是形容詞或形容詞短語。現(xiàn)在還沒有特定的規(guī)則或行之有效的約定來命名注解類型皮钠。
名詞稳捆,采用大駝峰命名法,盡量避免縮寫麦轰,除非該縮寫是眾所周知的眷柔, 比如HTML
, URL
期虾,如果類名稱中包含單詞縮寫,則單詞縮寫的每個(gè)字母均應(yīng)大寫驯嘱。
類
描述
例如Activity 類
Activity為后綴標(biāo)識(shí)
歡迎頁面類WelcomeActivityAdapter類
Adapter 為后綴標(biāo)識(shí)
新聞詳情適配器 NewDetailAdapter解析類
Parser為后綴標(biāo)識(shí)
首頁解析類HomePosterParser工具方法類
Utils或Manager為后綴標(biāo)識(shí)(與系統(tǒng)或第三方的Utils區(qū)分)或功能+Utils
線程池管理類:ThreadPoolManager日志工具類:LogUtils(Logger也可)打印工具類:PrinterUtils數(shù)據(jù)庫類
以DBHelper后綴標(biāo)識(shí)
新聞數(shù)據(jù)庫:NewDBHelperService類
以Service為后綴標(biāo)識(shí)
時(shí)間服務(wù)TimeServiceBroadcastReceiver類
以Receiver為后綴標(biāo)識(shí)
推送接收J(rèn)PushReceiverContentProvider類
以Provider為后綴標(biāo)識(shí)
ShareProvider自定義的共享基礎(chǔ)類
以Base開頭
BaseActivity,BaseFragment測(cè)試類的命名以它要測(cè)試的類的名稱開始镶苞,以Test結(jié)束。例如:HashTest
或HashIntegrationTest
鞠评。接口(interface):命名規(guī)則與類一樣采用大駝峰命名法茂蚓,多以able或ible結(jié)尾,如 interface Runnable
剃幌、interface Accessible
聋涨。
注意:如果項(xiàng)目采用MVP,所有Model负乡、View牍白、Presenter的接口都以I為前綴,不加后綴抖棘,其他的接口采用上述命名規(guī)則茂腥。
3.3 方法名
方法名都以lowerCamelCase
風(fēng)格編寫。
方法名通常是動(dòng)詞或動(dòng)詞短語切省。
方法
說明initXX()
初始化相關(guān)方法,使用init為前綴標(biāo)識(shí)最岗,如初始化布局initView()isXX() checkXX()
方法返回值為boolean型的請(qǐng)使用is或check為前綴標(biāo)識(shí)getXX()
返回某個(gè)值的方法,使用get為前綴標(biāo)識(shí)setXX()
設(shè)置某個(gè)屬性值handleXX()/processXX()
對(duì)數(shù)據(jù)進(jìn)行處理的方法displayXX()/showXX()
彈出提示框和提示信息朝捆,使用display/show為前綴標(biāo)識(shí)updateXX()
更新數(shù)據(jù)saveXX()
保存數(shù)據(jù)resetXX()
重置數(shù)據(jù)clearXX()
清除數(shù)據(jù)removeXX()
移除數(shù)據(jù)或者視圖等般渡,如removeView();drawXX()
繪制數(shù)據(jù)或效果相關(guān)的,使用draw前綴標(biāo)識(shí)
3.4 常量名
常量名命名模式為CONSTANT_CASE
芙盘,全部字母大寫驯用,用下劃線分隔單詞。那儒老,到底什么算是一個(gè)常量蝴乔?
每個(gè)常量都是一個(gè)靜態(tài)final
字段,但不是所有靜態(tài)final
字段都是常量贷盲。在決定一個(gè)字段是否是一個(gè)常量時(shí)淘这,考慮它是否真的感覺像是一個(gè)常量剥扣。例如巩剖,如果任何一個(gè)該實(shí)例的觀測(cè)狀態(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)為scopeVariableNameType
晦炊。
scope:范圍
非公有鞠鲜,非靜態(tài)字段命名以m開頭宁脊。
靜態(tài)字段命名以s開頭。
公有非靜態(tài)字段命名以p開頭贤姆。
公有靜態(tài)字段(全局變量)命名以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個(gè)字符的前綴必須小寫霞捡,前綴后面是由表意性強(qiáng)的一個(gè)單詞或多個(gè)單詞組成的名字坐漏,而且每個(gè)單詞的首寫字母大寫,其它字母小寫碧信,這樣保證了對(duì)變量名能夠進(jìn)行正確的斷句赊琳。
Type:類型
考慮到Android中使用很多UI控件,為避免控件和普通成員變量混淆以及更好達(dá)意砰碴,所有用來表示控件的成員變量統(tǒng)一加上控件縮寫作為后綴(文末附有縮寫表)躏筏。
對(duì)于普通變量一般不添加類型后綴,如果統(tǒng)一添加類型后綴呈枉,請(qǐng)參考文末的縮寫表趁尼。
用統(tǒng)一的量詞通過在結(jié)尾處放置一個(gè)量詞,就可創(chuàng)建更加統(tǒng)一的變量碴卧,它們更容易理解弱卡,也更容易搜索。
注意:如果項(xiàng)目中使用ButterKnife
住册,則不添加m前綴婶博,以lowerCamelCase
風(fēng)格命名。
例如荧飞,請(qǐng)使用mCustomerStrFirst
和mCustomerStrLast
酿傍,而不要使用mFirstCustomerStr
和mLastCustomerStr
。
量詞列表
量詞后綴說明
First
一組變量中的第一個(gè)
Last
一組變量中的最后一個(gè)
Next
一組變量中的下一個(gè)變量
Prev
一組變量中的上一個(gè)
Cur
一組變量中的當(dāng)前變量
說明:
集合添加如下后綴:List帝际、Map势篡、Set 數(shù)組添加如下后綴:Arr
注意:所有的VO(值對(duì)象)統(tǒng)一采用標(biāo)準(zhǔn)的lowerCamelCase風(fēng)格編寫,所有的DTO(數(shù)據(jù)傳輸對(duì)象)就按照接口文檔中定義的字段名編寫耳幢。
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 類名),后面加個(gè)大寫的T
(如:RequestT
, FooBarT
)嵌削。
更多還可參考~ 阿里巴巴Java開發(fā)手冊(cè)
4 資源文件規(guī)范
4.1 資源布局文件(XML文件(layout布局文件))
全部小寫毛好,采用下劃線命名法
4.1.1 contentView命名
必須以全部單詞小寫,單詞間以下劃線分割苛秕,使用名詞或名詞詞組肌访。
所有Activity或Fragment的contentView必須與其類名對(duì)應(yīng),對(duì)應(yīng)規(guī)則為:將所有字母都轉(zhuǎn)為小寫艇劫,將類型和功能調(diào)換(也就是后綴變前綴)吼驶。
例如:activity_main.xml
4.1.2 Dialog命名
規(guī)則:dialog_描述.xml
例如:dialog_hint.xml
4.1.3 PopupWindow命名
規(guī)則:ppw_描述.xml
例如:ppw_info.xml
4.1.4 列表項(xiàng)命名
規(guī)則:item_描述.xml
例如:item_city.xml
4.1.5 包含項(xiàng)命名
規(guī)則:模塊_(位置)描述.xml
例如:activity_main_head.xml
、activity_main_bottom.xml
注意:通用的包含項(xiàng)命名采用:項(xiàng)目名稱縮寫_描述.xml
例如:xxxx_title.xml
4.2 資源文件(圖片drawable文件夾下)
全部小寫店煞,采用下劃線命名法蟹演,加前綴區(qū)分
命名模式:可加后綴 small
表示小圖, big
表示大圖顷蟀,邏輯名稱可由多個(gè)單詞加下劃線組成酒请,采用以下規(guī)則:
用途模塊名邏輯名稱
用途模塊名顏色
用途_邏輯名稱
用途_顏色
說明:用途也指控件類型(具體見附錄UI控件縮寫表)
例如:
名稱
說明
btn_main_home.png
按鍵用途模塊名邏輯名稱
divider_maket_white.png
分割線用途模塊名顏色
ic_edit.png
圖標(biāo)用途_邏輯名稱
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
默認(rèn)搜索界面單元圖片用途模塊名邏輯名稱
ic_more_help
更多幫助圖標(biāo)用途_邏輯名稱
divider_list_line
列表分割線用途_邏輯名稱
sel_search_ok
搜索界面確認(rèn)選擇器用途模塊名邏輯名稱
shape_music_ring
音樂界面環(huán)形形狀用途模塊名邏輯名稱
如果有多種形態(tài),如按鈕選擇器:sel_btn_xx.xml
名稱
說明
sel_btn_xx
按鈕圖片使用btn_整體效果
(selector)
btn_xx_normal
按鈕圖片使用btn_正常情況效果
btn_xx_pressed
按鈕圖片使用btn_點(diǎn)擊時(shí)候效果
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鸣个,前提是命名要規(guī)范羞反。
4.3 動(dòng)畫文件(anim文件夾下)
全部小寫,采用下劃線命名法囤萤,加前綴區(qū)分昼窗。
具體動(dòng)畫采用以下規(guī)則:模塊名邏輯名稱
。
例如:refresh_progress.xml
阁将、market_cart_add.xml
膏秫、market_cart_remove.xml
右遭。
普通的tween動(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
中間縮小
4.4 values中name命名
4.4.1 colors.xml
colors.xml
的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值,這使如果需要改變基本色變的很復(fù)雜图筹。同時(shí)帅刀,這些定義是跟一些環(huán)境關(guān)聯(lián)起來的,如button
或者comment
, 應(yīng)該放到一個(gè)按鈕風(fēng)格中远剩,而不是在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>
向應(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
。
4.4.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)格或布局是非常容易禁谦。
4.4.3 strings.xml
strings
的name
命名使用下劃線命名法胁黑,采用以下規(guī)則:模塊名+邏輯名稱
,這樣方便同一個(gè)界面的所有string都放到一起州泊,方便查找丧蘸。
名稱
說明
main_menu_about
主菜單按鍵文字
friend_title
好友模塊標(biāo)題欄
friend_dialog_del
好友刪除提示
login_check_email
登錄驗(yàn)證
dialog_title
彈出框標(biāo)題
button_ok
確認(rèn)鍵
loading
加載文字
4.4.4 styles.xml
style
的name
命名使用大駝峰命名法,幾乎每個(gè)項(xiàng)目都需要適當(dāng)?shù)氖褂胹tyle
文件遥皂,因?yàn)閷?duì)于一個(gè)視圖來說有一個(gè)重復(fù)的外觀是很常見的力喷,將所有的外觀細(xì)節(jié)屬性(colors
刽漂、padding
、font
)放在style
文件中弟孟。 在應(yīng)用中對(duì)于大多數(shù)文本內(nèi)容贝咙,最起碼你應(yīng)該有一個(gè)通用的style
文件,例如:
<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:****
的屬性放到一個(gè)通用的style
中。
將一個(gè)大的styles.xml
文件分割成多個(gè)文件陈症, 你可以有多個(gè)styles.xml
文件蔼水。Android SDK支持其它文件,styles.xml
這個(gè)文件名稱并沒有作用录肯,起作用的是在文件里的<style>
標(biāo)簽徙缴。因此你可以有多個(gè)style文件,如styles.xml
嘁信、styles_home.xml
于样、styles_item_details.xml
、styles_forms.xml
潘靖。 不同于資源文件路徑需要為系統(tǒng)構(gòu)建起的有意義穿剖,在res/values
目錄下的文件可以任意命名。
4.5 layout中的id命名
命名模式為:view縮寫模塊名邏輯名
卦溢,比如btn_main_search
使用AndroidStudio
的插件ButterKnife Zelezny
糊余,生成注解非常方便,原生的話可以使用Android Code Generator
插件单寂。
如果想對(duì)資源文件進(jìn)行分包可以參考我這篇文章~ Android Studio下對(duì)資源進(jìn)行分包
5 版本統(tǒng)一規(guī)范
Android開發(fā)存在著眾多版本的不同贬芥,比如compileSdkVersion
、minSdkVersion
宣决、targetSdkVersion
以及項(xiàng)目中依賴第三方庫的版本蘸劈,不同的module及不同的開發(fā)人員都有不同的版本,所以需要一個(gè)統(tǒng)一版本規(guī)范的文件尊沸。
具體可以參考我寫的這篇博文~ Android開發(fā)之版本統(tǒng)一規(guī)范
6 第三方庫規(guī)范
別再閉門造車了威沫,用用最新最火的技術(shù)吧,安利一波~ Android 流行框架查速表洼专,順便帶上自己的干貨~ Android開發(fā)人員不得不收集的代碼
希望Team能用時(shí)下較新的技術(shù)棒掠,對(duì)開源庫的選取,一般都需要選擇比較穩(wěn)定的版本屁商,作者在維護(hù)的項(xiàng)目烟很,要考慮作者對(duì)issue的解決,以及開發(fā)者的知名度等各方面。選取之后雾袱,一定的封裝是必要的恤筛。
個(gè)人推薦Team可使用如下優(yōu)秀輪子:
Retrofit
RxAndroid
OkHttp
Glide / Fresco
Gson / Fastjson
EventBus / AndroidEventBus
GreenDao
Dagger2(選用)
Tinker(選用)
7 注釋規(guī)范
為了減少他人閱讀你代碼的痛苦值,請(qǐng)?jiān)陉P(guān)鍵地方做好注釋谜酒。
7.1 類注釋
每個(gè)類完成后應(yīng)該有作者姓名和聯(lián)系方式的注釋,對(duì)自己的代碼負(fù)責(zé)妻枕。
/** * <pre> * author : Blankj * e-mail : xxx@xx * time : 2017/03/07 * desc : xxxx描述 * version: 1.0 * </pre> */public class WelcomeActivity { ...}
具體可以在AS中自己配制僻族,Settings → Editor → File and Code Templates → Includes → File Header,輸入
/** * <pre> * author : ${USER} * e-mail : xxx@xx * time : ${YEAR}/${MONTH}/${DAY} * desc : * version: 1.0 * </pre> */
這樣便可在每次新建類的時(shí)候自動(dòng)加上該頭注釋屡谐。
7.2 方法注釋
每一個(gè)成員方法(包括自定義成員方法述么、覆蓋方法、屬性方法)的方法頭都必須做方法頭注釋愕掏,在方法前一行輸入/** + 回車
或者設(shè)置Fix doc comment
(Settings → Keymap → Fix doc comment)快捷鍵度秘,AS便會(huì)幫你生成模板,我們只需要補(bǔ)全參數(shù)即可饵撑,如下所示剑梳。
/** * bitmap轉(zhuǎn)byteArr * * @param bitmap bitmap對(duì)象 * @param format 格式 * @return 字節(jié)數(shù)組 */public static byte[] bitmap2Bytes(Bitmap bitmap, CompressFormat format) { if (bitmap == null) return null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(format, 100, baos); return baos.toByteArray();}
7.3 塊注釋
塊注釋與其周圍的代碼在同一縮進(jìn)級(jí)別。它們可以是/* ... /
風(fēng)格滑潘,也可以是// ...
風(fēng)格(//
后最好帶一個(gè)空格)垢乙。對(duì)于多行的/ ... /
注釋,后續(xù)行必須從
開始语卤, 并且與前一行的*
對(duì)齊追逮。以下示例注釋都是OK的。
/* * This is // And so /* Or you can * okay. // is this. * even do this. */ */
注釋不要封閉在由星號(hào)或其它字符繪制的框架里粹舵。
Tip:在寫多行注釋時(shí)钮孵,如果你希望在必要時(shí)能重新?lián)Q行(即注釋像段落風(fēng)格一樣),那么使用/* ... */
眼滤。
7.4 其他一些注釋
AS已幫你集成了一些注釋模板巴席,我們只需要直接使用即可,在代碼中輸入todo
诅需、fixme
等這些注釋模板情妖,回車后便會(huì)出現(xiàn)如下注釋
// TODO: 17/3/14 需要實(shí)現(xiàn),但目前還未實(shí)現(xiàn)的功能的說明// FIXME: 17/3/14 需要修正诱担,甚至代碼是錯(cuò)誤的毡证,不能工作,需要修復(fù)的說明
8 測(cè)試規(guī)范
業(yè)務(wù)開發(fā)完成之后蔫仙,開發(fā)人員做單元測(cè)試料睛,單元測(cè)試完成之后,保證單元測(cè)試全部通過同時(shí)單元測(cè)試代碼覆蓋率達(dá)到一定程度(這個(gè)需要開發(fā)和測(cè)試約定,理論上越高越好)恤煞,開發(fā)提測(cè)屎勘。
// TODO...
9 RN規(guī)范
// TODO...
10 其他的一些規(guī)范
合理布局,有效運(yùn)用<merge>
居扒、<ViewStub>
概漱、<include>
標(biāo)簽;
Activity
和Fragment
里面有許多重復(fù)的操作以及操作步驟喜喂,所以我們都需要提供一個(gè)BaseActivity
和BaseFragment
瓤摧,讓所有的Activity
和Fragment
都繼承這個(gè)基類。
啟動(dòng)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);}
同理,啟動(dòng)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;}
方法基本上都按照調(diào)用的先后順序在各自區(qū)塊中排列这揣;
相關(guān)功能作為小區(qū)塊放在一起(或者封裝掉);
當(dāng)一個(gè)類有多個(gè)構(gòu)造函數(shù)影斑,或是多個(gè)同名方法给赞,這些函數(shù)/方法應(yīng)該按順序出現(xiàn)在一起,中間不要放進(jìn)其它函數(shù)/方法矫户;
數(shù)據(jù)提供統(tǒng)一的入口塞俱。無論是在 MVP、MVC 還是 MVVM 中吏垮,提供一個(gè)統(tǒng)一的數(shù)據(jù)入口障涯,都可以讓代碼變得更加易于維護(hù)。比如可使用一個(gè)DataManager
膳汪,把 http
唯蝶、preference
、eventpost
遗嗽、database
都放在DataManger
里面進(jìn)行操作粘我,我們只需要與DataManger
打交道;
多用組合, 少用繼承痹换;
提取方法, 去除重復(fù)代碼征字。對(duì)于必要的工具類抽取也很重要,這在以后的項(xiàng)目中是可以重用的娇豫。
可引入 Dagger2 減少模塊之間的耦合性匙姜。Dagger2 是一個(gè)依賴注入框架,使用代碼自動(dòng)生成創(chuàng)建依賴關(guān)系需要的代碼冯痢。減少很多模板化的代碼氮昧,更易于測(cè)試框杜,降低耦合,創(chuàng)建可復(fù)用可互換的模塊袖肥;
項(xiàng)目引入RxJava
- RxAndroid
這些響應(yīng)式編程咪辱,可以極大的減少邏輯代碼;
通過引入事件總線椎组,如:EventBus
油狂、AndroidEventBus
、RxBus
寸癌,它允許我們?cè)贒ataLayer
中發(fā)送事件专筷,以便ViewLayer
中的多個(gè)組件都能夠訂閱到這些事件,減少回調(diào)灵份;
盡可能使用局部變量仁堪;
及時(shí)關(guān)閉流哮洽;
盡量減少對(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操作匪凉;
盡量使用HashMap枪眉、ArrayList、StringBuilder再层,除非線程安全需要贸铜,否則不推薦使用Hashtable、Vector聂受、StringBuffer蒿秦,后三者由于使用同步機(jī)制而導(dǎo)致了性能開銷;
盡量在合適的場合使用單例蛋济;
使用單例可以減輕加載的負(fù)擔(dān)棍鳖、縮短加載的時(shí)間、提高加載的效率碗旅,但并不是所有地方都適用于單例渡处,簡單來說,單例主要適用于以下三個(gè)方面:
(1)控制資源的使用祟辟,通過線程同步來控制資源的并發(fā)訪問
(2)控制實(shí)例的產(chǎn)生医瘫,以達(dá)到節(jié)約資源的目的
(3)控制數(shù)據(jù)的共享,在不建立直接關(guān)聯(lián)的條件下旧困,讓多個(gè)不相關(guān)的進(jìn)程或線程之間實(shí)現(xiàn)通信
把一個(gè)基本數(shù)據(jù)類型轉(zhuǎn)為字符串登下,基本數(shù)據(jù)類型.toString()
是最快的方式茫孔、String.valueOf(數(shù)據(jù))
次之、數(shù)據(jù) + ""
最慢被芳;
使用AS自帶的Lint來優(yōu)化代碼結(jié)構(gòu)(什么缰贝,你不會(huì)?右鍵module畔濒、目錄或者文件剩晴,選擇Analyze → Inspect Code);
最后不要忘了內(nèi)存泄漏的檢測(cè)侵状;
最后啰嗦幾句:
好的命名規(guī)則能夠提高代碼質(zhì)量赞弥,使得新人加入項(xiàng)目的時(shí)候降低理解代碼的難度;
規(guī)矩終究是死的趣兄,適合團(tuán)隊(duì)的才是最好的绽左;
命名規(guī)范需要團(tuán)隊(duì)一起齊心協(xié)力來維護(hù)執(zhí)行,在團(tuán)隊(duì)生活里艇潭,誰都不可能獨(dú)善其身拼窥;
一開始可能會(huì)有些不習(xí)慣,持之以恒蹋凝,總會(huì)成功的鲁纠。
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的圖標(biāo))
color
cl(主要用于顏色值)
average
avg
background
bg(主要用于布局和子布局的背景)
selector
sel主要用于某一view多種狀態(tài),不僅包括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包命名規(guī)范
Android 開發(fā)最佳實(shí)踐
Android 編碼規(guī)范
阿里巴巴Java開發(fā)手冊(cè)
Google Java編程風(fēng)格指南
小細(xì)節(jié)迄汛,大用途捍壤,35 個(gè) Java 代碼性能優(yōu)化總結(jié)!
版本日志
17/03/06: 發(fā)布初版 鞍爱;
17/03/07: 修訂目錄排版鹃觉,完善某些細(xì)節(jié);
17/03/08: 規(guī)范排版硬霍,修復(fù)typor及新增一些規(guī)范帜慢;
17/03/13: 新增其他注釋;
17/03/14: 包名劃分為按功能劃分唯卖;
——powered by Blankj(蔡夢(mèng)杰)