轉載請把頭部出處鏈接和尾部2維碼1起轉載,本文出自逆流的魚yuiop:http://blog.csdn.net/hejjunlin/article/details/52602487
前言:Android中1些開發規范,避免給自己和他人少留坑。
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
- src/androidTest
- src/test
- src/commonTest
- src/main
- androidTest - 功能測試目錄
- test - 單元測試目錄
- commonTest - 為AndroidTest & Test 提供的同享測試代碼的目錄
- main - 利用代碼目錄
當你修改或增加新功能的時候,工程結構仍然應當保持如上的模樣。
使用如上的工程結構可讓我們的利用代碼從相干的測試代碼中分離出來。
CommonTest目錄使得我們的功能測試和單元測試可以同享部份代碼,比如mock model creation and dagger test configuration classes.
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
AndroidActivity, NetworkHelper, UserFragment, PerActivity
任何繼承自android組件的類都應當使用組件名稱來結尾,比如:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
UserFragment, SignUpActivity, RateAppDialog, PushNotificationServer, NumberView
用android組件名稱結尾的繼承類能夠清楚的標識出類的用處,比如,如果要去查找修改RegistrationDialog時,那末這個命名使得定位這個類文件非常方便。
1.2.2.1 Drawable 文件
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
Type | Prefix | Example |
---|---|---|
Selector | selector_ | selector_button_cancel |
Background | bg_ | bg_rounded_button |
Circle | circle_ | circle_white |
Progress | progress_ | progress_circle_purple |
Divider | divider_ | divider_grey |
在Android Studio中這個命名約定仍然可以幫助我們將類似的組織到1起
并清晰的標識出這1文件用作甚么
比如, 命令1個資源為“button_cancel”不能標識任何信息
這是1個selector資源呢還是1個圓角按鈕背景呢?
正確的命名可以去除所有的引發的模糊不清.
在創建selector不同狀態資源時,也應當使用對應的命名下標:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
State | Suffix | Example |
---|---|---|
Normal | _normal | btn_accept_normal |
Pressed | _pressed | btn_accept_pressed |
Focused | _focused | btn_accept_focused |
Disabled | _disabled | btn_accept_disabled |
Selected | _selected | btn_accept_selected |
使用如上清晰的下標絕對明顯的標識出了selector狀態資源的作用。
為有色彩和其他標識的資源文件增加下標,使得開發者在打開selector文件時就能夠知道不同的selector資源的狀態是甚么
1.2.2.2 Layout 文件
在命名布局文件時,應當用android組件的名稱作為文件名的前綴,比如:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
Component | Class Name | Layout Name |
---|---|---|
Activity | MainActivity | activity_main |
Fragment | MainFragment | fragment_main |
Dialog | RateDialog | dialog_rate |
Widget | UserProfileView | view_user_profile |
AdapterView | Item | N/A item_follower |
注意:如果要創建的布局文件是有多個不同組件使用的,那末應當使用”layout_”前綴
這樣不但在層級目錄中可以很方便的找到文件,
這樣也能夠幫助我們定義相應的這個layout布局文件歸屬的類。
1.2.2.3 Menu Files
菜單文件不需要使用“menu_”前綴。
在資源目錄下已有菜單包了,所以這是沒必要要的。
1.2.2.4 Values Files
所有的資源文件名必須是復數的,比如:
attrs.xml, strings.xml, styles.xml, colors.xml, dimens.xml
2、代碼相干
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
public void setUserId(String id) {
try {
mUserId = Integer.parseInt(id);
} catch (NumberFormatException e) { }
}
如果這里出現問題,這里不會打印出任何信息,而且也很難debug,只能讓人迷惑。
當catch1個異常時,我們總是需要輸出error日志到控制臺,用于調試,如果必要的話,需要正告用戶這個異常。比如:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
public void setCount(String count) {
try {
count = Integer.parseInt(id);
} catch (NumberFormatException e) {
count = 0;
Log.e(TAG, "There was an error parsing the count " + e);
DialogFactory.showErrorMessage(R.string.error_message_parsing_count);
}
}
這里我們有以下的方式處理出錯:
2.1.2 不要catch最大的異常(Exception):
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
public void openCustomTab(Context context, Uri uri) {
Intent intent = buildIntent(context, uri);
try {
context.startActivity(intent);
} catch (Exception e) {
Log.e(TAG, "There was an error opening the custom tab " + e);
}
}
為何不這樣做呢?
在大部份情況下,catch這個大的Exception或Throwable都是不適合的。(特別是Throwable由于它包括Error的異常。)
這樣意味著你沒有期望到的終究要捕獲的異常(包括RuntimeExceptions像CLassCastException)都被捕獲并在利用層進行error處理,這樣是很危險的。
如果有人在你調用的代碼里添加了1個新的類型的異常,編譯器不會幫你認識到你需要處理這個不同的毛病類型。這是你代碼里很難發現的毛病處理方式。
大多數情況下,你不應當用相同的處理方式來處理不同的exception.
以下,catch期望的異常并正確的處理:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
public void openCustomTab(Context context, Uri uri) {
Intent intent = buildIntent(context, uri);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "There was an error opening the custom tab " + e);
}
}
2.1.3 組織 exceptions
在異常運行相同的代碼的地方,他們應當增加可讀性和避免代碼復制。比如,你可能會像以下這樣處理異常:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
public void openCustomTab(Context context, @Nullable Uri uri) {
Intent intent = buildIntent(context, uri);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "There was an error opening the custom tab " + e);
} catch (NullPointerException e) {
Log.e(TAG, "There was an error opening the custom tab " + e);
} catch (SomeOtherException e) {
// Show some dialog
}
}
你可以這樣做:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
public void openCustomTab(Context context, @Nullable Uri uri) {
Intent intent = buildIntent(context, uri);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e | NullPointerException e) {
Log.e(TAG, "There was an error opening the custom tab " + e);
} catch (SomeOtherException e) {
// Show some dialog
}
}
2.1.4 Using try-catch over throw exception
在exception出現的地方使用try-catch塊增加代碼可讀性
在代碼中error產生的地方就處理,這樣不論是debug還是更改error處理都很容易。
2.1.5 不要使用垃圾回收器
2.1.6 完全限制方式導包
2.1.7 去掉無用的包引入
2.2.1 屬性定義和命名
所有的字段都應當在文件頂部定義,遵守以下規則:
private, non-static 字段應當用“m”做前綴,像以下的例子是正確的:
mUserSignedIn, mUserNameText, mAcceptButton
所有其他的字段都用小寫字母開頭:
int numOfChildren; String username;
static final 字段(靜態的)全部大寫
private static final int PAGE_COUNT = 0;
2.2.1.2 View屬性名稱
當為1個界面控件定義1個類屬性時,view應當作為這個屬性的后綴,比如:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
View | Name |
---|---|
TextView | mUserNameView |
Button | mAcceptLoginButton |
ImageView | mProfileAvatarView |
RelativeLayout | mProfileLayout |
2.2.2 命名屬性時不要包括容器類型
2.2.3 避免類似的命名
2.2.4 數字連續命名
2.2.5 易讀的命名
在對屬性,方法和類命名時,應當遵守以下規則:
2.2.6 將帶縮寫詞(那些將所有字母都大寫的詞)作為單詞使用
在任意類名,變量名中使用的縮寫詞都應當作為單詞使用.比如:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
Do | Don’t |
---|---|
setUserId | setUserID |
String uri | String URI |
int id | int ID |
parseHtml | parseHTML |
generateXmlFile | generateXMLFile |
2.2.7 避免對齊變量聲明
任何變量的聲明都不應當使用特殊的對齊格式,比如:
這樣就很好:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
private int userId = 8;
private int count = 0;
private String username = "hitherejoe";
不要這樣做:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
private String username = "hitherejoe";
private int userId = 8;
private int count = 0;
這樣產生了很多空白,讓代碼難于瀏覽.
2.2.8 使用空格符進行縮進
對語句塊,應當使用4個空格符縮進:
if (userSignedIn) {
count = 1;
}
在自動換行時,應當使用8個空格符縮進:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
String userAboutText =
"This is some text about the user and it is pretty long, can you see!"
2.2.9 If-Statement語句
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
class SomeClass
{
private void someFunction()
{
if (isSomething)
{
}
else if (!isSomethingElse)
{
}
else
{
}
}
}
取而代之應當這樣:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
class SomeClass {
private void someFunction() {
if (isSomething) {
} else if (!isSomethingElse) {
} else {
}
}
}
這不但是沒有必要增加額外的1行,而它還會讓讀取代碼變得更加容易
2.2.9.2 Inline if-clauses 內聯if從句
2.2.9.3 Nested if-conditions 嵌套的if條件語句
在可能的情況下,if語句的條件應當合并,避免過于復雜的嵌套,例如:
推薦:
if (userSignedIn && userId != null) {
}
避免像下面這樣:
if (userSignedIn) {
if (userId != null) {
}
}
這會使得代碼更加容易瀏覽,并且從嵌套語句中移除沒必要要的行數。
userStatusImage = signedIn ? R.drawable.ic_tick : R.drawable.ic_cross;
它比下面的代碼占用更少的行數:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
if (signedIn) {
userStatusImage = R.drawable.ic_tick;
} else {
userStatusImage = R.drawable.ic_cross;
}
注意:在有些情況下雙目運算符不應當使用。如果if語句的邏輯過于復雜或包括了大量的字符,這時候應當使用標準的大括號樣式。
2.2.10 Annotations 注解
2.2.10.1 Annotation practices 注解用法
從《Android code style guidelines》中得悉:
@Nullable TextView userNameText;
private void getName(@Nullable String name) { }
2.2.10.2 Annotation style 注解樣式
利用在方法或類的注解應當總是在聲明中定義,并且每項只能1行:
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
@Annotation
@AnotherAnnotation
public class SomeClass {
@SomeAnotation
public String getMeAString() {
}
}
當在屬性上使用注解時,應確保注解與屬性在同1行,例如:
@Bind(R.id.layout_coordinator) CoordinatorLayout mCoordinatorLayout;
@Inject MainPresenter mMainPresenter;
它會使得聲明瀏覽起來更加容易。例如,在聲明 ‘@Inject SomeComponent mSomeName’ 可讀為’inject this component with this name’(利用這個名字注入組件)。
2.2.11 Limit variable scope 限制變量的作用域
2.2.12 Unused elements 無用的元素
2.2.13 Order Import Statements 導入聲明
由于我們使用的是Android Studio,因此導入都是自動的按序導入。但是,在1些情況下并不是如此,因此應依照下面的順序導入:
注意:
- 1.每一個組的導入應依照字母的順序排列,大寫字母排在小寫字母之前(Z排在a之前)
- 2.在各個組之間應當空1行(android, com, JUnit, net, org, java, javax)
2.2.14 Logging 日志
日志通常在開發進程中用于記錄有用的毛病消息或其他可能有用的信息。
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
Log | Reason |
---|---|
Log.v(String tag, String message) | verbose (詳細) |
Log.d(String tag, String message) | debug(調試) |
Log.i(String tag, String message) | information(普通info) |
Log.w(String tag, String message) | warning(正告) |
Log.e(String tag, String message) | error (毛病) |
我們做日志記錄時可以設置1個標示,這個TAG是1個靜態的final屬性,放置在類的頂部,例如:
private static final String TAG = MyActivity.class.getName();
所有的調試日志不應當出現在發布的版本中,另外一方面,信息、正告和毛病日志只有在需要的時候保持開啟。
//create by 逆流的魚yuiop on 2016/9/21
//blog地址:http://blog.csdn.net/hejjunlin
if (BuildConfig.DEBUG) {
Log.d(TAG, "Here's a log message");
}
第1時間取得博客更新提示,和更多android干貨,源碼分析,歡迎關注我的微信公眾號,掃1掃下方2維碼或長按辨認2維碼,便可關注。
如果你覺得好,隨手點贊,也是對筆者的肯定,也能夠分享此公眾號給你更多的人,原創不容易