參考資料:我總結(jié)的Android編程規(guī)范
1. 命名規(guī)則
1.1 類名奈偏,接口名:
以大寫開頭淮捆,如果一個類的類名由多個單詞組成郁油,所有單詞的首字母必須大寫,單詞盡量寫全稱攀痊,不要簡寫桐腌,除非約定俗成的名字,例如:URL苟径,RTMP案站,RTSP 這些廣泛使用的專有名詞,可以全部大寫涩笤,也可以首字母大寫嚼吞。
例如:HttpRequest
盒件,CourseActivity
1.2 局部變量蹬碧,類的成員變量,類的成員函數(shù)炒刁,函數(shù)參數(shù):
以小寫字母開頭其他的單詞首字母大寫恩沽,變量名不建議使用下劃線分隔單詞,建議使用駝峰命名法翔始,Android 的系統(tǒng)類都采用此方法罗心。
例如:toString()
,onCreateView(Bundle saveInstanceState)
1.3 靜態(tài)常量:
常量單詞全部大寫城瞎,所以單詞之間使用下劃線分隔渤闷。
例如:WHAT_EMPTY_CONTENT
1.4 控件變量的命令,控件的ID命名:
建議:xml 布局文件中的控件的id的命令與*.java的代碼文件中的空間對象的命名保持一致脖镀。
class MyActivity extends Activity {
TextView txtUserName;
...
void onCreate(Bundle saveInstanceState) {
txtUserName = (TextView) findViewById(R.id.txtUserName);
}
}
1.5 常用控件以及類對象命名的規(guī)范說明:
類名 | 變量名 | 類名 | 變量名 |
---|---|---|---|
TextView | txtDescription | ProgressBar | progressDescription |
Button | btnDescription | SeekBar | seekBarDescription |
ImageButton | imgBtnDescription | VideoView | vvDescription |
ImageView | imgDescription | Spinner | spinDescription |
RadioButton | rbDescription | WebView | webViewDescription |
EditText | editDescription | ListView | listViewDescription |
ScrollView | scrollDescription | GridView | gridDescription |
Handler | descriptionHandler | RatingBar | ratingBarDescription |
PullToRefreshListView | pullRefreshViewDescription | Adapter | descriptionAdapter |
Fragment | descriptionFragment | Activity | descriptionActivity |
List<T> | descriptionList | Map<> | mapDescription |
SlidingMenu | slidMenuDescription | ViewPager | viewPagerDescription |
CheckBox | chBoxDescription | View | viewDescription |
RadioGroup | rgDescription | ExpandableListView | expDescription |
FrameLayout | frameLayDescription | SharedPreferences | spDescription |
LinearLayout | lineLayDescription | RelativeLayout | relativeLayDescription |
startActivityForResult(requestCode) | REQUEST_CODE_DESCRIPTION | msg.what | WHAT_DESCRIPTION |
1.6 資源命名:
-
layout
資源文件的命名(全部小寫飒箭,下劃線分隔):-
activity
資源文件:activity_description1_description2.xml -
fragment
資源文件:fragment_description1_description2.xml -
listview
列表項(xiàng)資源文件:list_item_description1_description2.xml - 可復(fù)用(被include)的組件資源文件:control_description1_description2.xml
-
drawable
資源:controlName_description1_description2_selector.xml-
controlName
表示該資源要用在什么類型的控件上,例如:如果是按鈕的圖片切換則應(yīng)該命名為button_bg_sendmessage_selector.xml
-
selector
表示該資源的形式蜒灰,例如還有shape
等
-
-
- 圖片資源的命名:同上
- 顏色值的命名:
color_description
以color
為前綴弦蹂,全部小寫,下劃線分割强窖。
description
既可以是該顏色使用的功能描述凸椿,也可以是該顏色的英文描述,也可以是具體的顏色值翅溺,例如:
<color name="color_white">#ffffff</color>
<color name="color_grey_ccc">#cccccc</color>
<color name="color_grey_ddd">#dddddd</color>
因?yàn)間rey可能有很多的等級脑漫,有時候需要不同等級的灰色髓抑,沒有那么多英文名可以區(qū)分,所以名字中可以直接使用顏色值
<color name="color_button_pressed">#4c4c4c</color>
根據(jù)功能定義description优幸,表示該顏色用于按鈕按下
注:不允許出現(xiàn)毫無意義的命名启昧,例如 textview1, textview2
2. 關(guān)于字面常量
代碼中不允許出現(xiàn)直接硬編碼的字面常量,如果是控件上顯示的文本劈伴,必須放在string.xml
資源文件中密末。如果是代碼中用到的常量字符串,必須定義成public static final String
類型的常量值跛璧,在代碼中使用該定義的常量值严里。
這樣做的好處是以后需要修改該常量值,只需要修改一個地方追城。如果是硬編碼在代碼中則需要修改所有使用它的地方刹碾,而且拷貝容易出錯。
在Activity
之間傳遞參數(shù)的時候座柱,intent.putExtra
的key值
也要符合命名規(guī)范迷帜,并且統(tǒng)一定義為靜態(tài)常量,不能直接硬編碼在代碼中色洞,否則想要修改的時候非常麻煩戏锹。某一個Activity
在被啟動的時候需要接受參數(shù),那么這些參數(shù)的key
定義就應(yīng)該放在該Activity
中火诸。
3. JSON解析
Android中調(diào)用服務(wù)器端的接口一般返回的是JSON
數(shù)據(jù)锦针,在解析JSON
的時候,無論是使用原始的手工解析方式置蜀,還是使用javabean
的解析方式奈搜,解析出來的結(jié)果在使用的時候必須都進(jìn)行判空處理。不允許因?yàn)榉?wù)端的json
出問題盯荤,導(dǎo)致app在解析json
的時候出現(xiàn)崩潰馋吗。
4. 類成員初始化
所有類的成員變量一定要賦初始值,不允許只定義秋秤,不賦值宏粤。
5. Int類型常量
函數(shù)返回的時候,如果返回的int類型的數(shù)據(jù)并不是真實(shí)的實(shí)用的數(shù)據(jù)值(例如表示寬度航缀、高度商架、大小等值),僅僅代表函數(shù)執(zhí)行成功芥玉、失敗蛇摸、異常的狀態(tài)值,并且這些值是有限的幾個值灿巧,必須要將這些值使用靜態(tài)常量描述赶袄,或者使用枚舉類型揽涮,例如:
int GetJsonString()
該函數(shù)返回-1表示獲取解析JSON
數(shù)據(jù)異常,返回0表示成功饿肺,返回1表示網(wǎng)絡(luò)連接異常蒋困,返回2表示JSON
內(nèi)容中的數(shù)據(jù)部分為空。
那么在函數(shù)內(nèi)部的代碼里不要直接使用這些字面值敬辣,這些字面值對于程序員來說是毫無意義的雪标,代碼可閱讀性很差,建議做成下面的模式:
public static final int RESULT_PARSE_JSON_EXCEPTION = -1;
public static final int RESULT_SUCCESS = 0;
public static final int RESULT_NETWORK_EXCEPTION = 1;
public static final int RESULT_NO_DATA = 2;
使用這些符號常量值代替字面值的好處是溉跃,符號常量值是由大寫的英文單詞組成村刨,是有意義的,可以幫助程序員更好的理解函數(shù)返回值的意義撰茎,而且符號常量值對應(yīng)的具體的賦值在后期也是很方便修改的嵌牺。
6. Activity 接受參數(shù)與模塊化
如果一個Activity
可能在多個地方被打開,或者一個Fragment
可能在多個地方被用到龄糊。那么在設(shè)計(jì)該Activity
和Fragment
的時候一定要考慮低耦合逆粹,對外提供統(tǒng)一的參數(shù)接口,啟動Activity
的過程封裝在該Activity類
的靜態(tài)成員方法里炫惩。
類似如下:
class MyActivity extends Activity {
...
public static void startActivity(Context context, Params param) {
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra("param", param);
startActivity(intent);
}
public static void startActivityForResult(Context context, Params param) {
Intent intent = new Intent(context, MyActivity.class)
intent.putExtra("param", param);
startActivityForResult(intent, REQUEST_CODE);
}
}
參數(shù)的傳遞最好是封裝在一個Model實(shí)體中
僻弹,避免使用Map
這種方式進(jìn)行參數(shù)傳遞。建議該實(shí)體類實(shí)現(xiàn)為對應(yīng)的Activity
的靜態(tài)可序列化的內(nèi)部類诡必。
7. Android Studio 工程目錄組織
Android Studio 中的項(xiàng)目的包結(jié)構(gòu)應(yīng)該根據(jù)工程各個部分的功能來組織奢方。
8. Handler 的封裝
每個Activity
里面幾乎都會定義一個Handler內(nèi)部類
搔扁,但是很多Activity
里面的Handler
都使用了重復(fù)的消息類型爸舒,這里面是有冗余代碼的,所以應(yīng)該把這些Activity
都是用到的Handler
類的消息部分稿蹲,提取成一個公共的Handler
類扭勉。
然后在各個Activity
里面使用繼承的方式,來提供該Activity
特有的Handler
消息類型的Handler
類實(shí)現(xiàn)苛聘。
另外Handler
發(fā)送消息應(yīng)該使用Handler
類的成員函數(shù)涂炎,不應(yīng)該直接使用handler.obtainMessage(xxx).sendToTarget();
這種原始的發(fā)送消息的方式,這樣不利于降低耦合设哗,這種細(xì)節(jié)應(yīng)該隱藏在Handler
類的里面唱捣。
Handler
的消息類型應(yīng)該定義為Handler
類里面的靜態(tài)常量,而該常量不應(yīng)是public
的网梢,對外部不可見震缭。也就是說使用handler
對象發(fā)送消息的細(xì)節(jié)不應(yīng)該暴露給外部。
9. List 數(shù)據(jù)更新
封裝ListView
的數(shù)據(jù)更新战虏,在handlerMessage
中更新數(shù)據(jù)拣宰,避免出現(xiàn)java.lang.IllegalStateException
問題
10. Activity 與 Fragment 之間傳遞參數(shù)
Activity
與Fragment
的數(shù)據(jù)傳遞采用interface
的方式党涕,也就是代理的方式,這樣可以降低耦合巡社,有利于Fragment
的復(fù)用:
在你的fragment
中定義一個接口:
public interface OnDataPass {
public void onDataPass(String data);
}
然后膛堤,在你的fragment
中onAttach(Activity a)
方法中實(shí)例化一個OnDataPass
:
OnDataPass dataPasser;
@Override
public void onAttach(Activity a) {
super.onAttach(a);
dataPasser = (OnDataPass) a;
}
在你的fragment
中,當(dāng)你想處理傳遞的數(shù)據(jù)時晌该,只需要調(diào)用dataPasser
的onDataPass
方法即可:
public void passData(String data) {
dataPasser.onDataPass(data);
}
最后肥荔,在你的容器activity
中實(shí)現(xiàn)OnDataPass
接口:
public class MyActivity extends Activity implements OnDataPass {
...
@Override
public void onDataPass(String data) {
Log.d("LOG", "Hello " + data);
}
}
11. 網(wǎng)絡(luò)請求數(shù)據(jù)模塊化
一般在Activity
中我們通過網(wǎng)絡(luò)請求服務(wù)端的接口獲得數(shù)據(jù),這個過程一般是在一個線程中做的朝群,獲取到數(shù)據(jù)之后次企,再通過Activity
中的handler
發(fā)送消息來通知Activity
更新數(shù)據(jù)。
該負(fù)責(zé)獲取數(shù)據(jù)的線程類潜圃,我們一般都實(shí)現(xiàn)為一個Activity
的內(nèi)部類缸棵,該類可以直接訪問Activity
的成員變量,例如handler
谭期,數(shù)據(jù)列表對象等堵第。但是這樣不利于該數(shù)據(jù)獲取線程的復(fù)用。如果另一個Activity
里面也需要獲取相同的數(shù)據(jù)隧出,那么這個功能是不能復(fù)用的踏志。
所以這個負(fù)責(zé)數(shù)據(jù)請求的線程類,不應(yīng)該與具體的Handler
和Activity
聯(lián)系過于緊密胀瞪。應(yīng)該定義為一個靜態(tài)類针余,handler
應(yīng)該作為參數(shù)傳遞進(jìn)來,而不是直接訪問外部類的成員變量凄诞。
12. 封裝 Log 功能
Log
功能應(yīng)該封裝成為自動將當(dāng)前所在類的類名變成log輸出的TAG參數(shù)圆雁,發(fā)布的app最好是能循環(huán)寫日志文件到系統(tǒng)存儲中,并且日志文件應(yīng)該使用反復(fù)覆蓋的方式重復(fù)利用帆谍。
下面僅僅是一個不完善的例子:
public class MyLog {
public static final String TAG = "myapp ";
public static void v(Object o, String message) {
Log.v(TAG + o.getClass().getSimpleName(), message);
}
}
使用方法:
MyLog(this, "Hello Log");
打印結(jié)果
V/myapp MainActivity: Hello Log
13. 版本控制
使用自動化版本管理伪朽,自動生成版本號,使應(yīng)用程序的版本與版本庫上保持一致汛蝙。
使用hg替換工程目錄下的app目錄下的build.gradle
文件即可烈涮,如果AndroidManifest.xml
里面也有版本號的設(shè)置,AndroidStudio還是以build.gradle
為準(zhǔn)窖剑。不應(yīng)該在每次發(fā)布的時候坚洽,在AndroidStudio的工程設(shè)置里面手工修改版本號。
14. 為程序添加全局異常捕獲
應(yīng)該為app添加全局異常捕獲西土,app中總會有一些我們未捕獲的異常讶舰,一旦用戶使用過程中遇到這樣的異常,程序就會崩潰,我們應(yīng)該檢測該類未捕獲的異常信息绘雁,程序崩潰的時候通過寫文件日志橡疼,或者發(fā)送郵件的方式獲得異常信息,以便解決bug庐舟。