天天看點

探讨Android開發值得注意的規範

有人說,國内一個開發者寫出的代碼可能有十種風格,國外十個開發者寫出的代碼卻是同一種風格。我最初在項目開發時深有體會(本人在開發初期也不注重代碼規範),一個項目裡面可能同時有picasso、imageLoader、fresco等多種圖檔加載架構,可能有OkHttp、Volley、XUtil等多種網絡請求架構,可能各自自定義BaseActivity,每個類、方法、成員變量沒有具體注釋,沒有從strings.xml引用字元串而是直接寫上,有些引用可能會空指針抛出空指針(null)沒有做異常處理。這一系列的不規範将成為項目維護以及後續的痛點。總結一下,統一規範的架構、代碼具有良好可讀性,利于項目維護和後續開發,便于團隊内部協同合作。

一、統一開發架構

開發前期應具體分析,敲定各種需要用到的架構:圖檔加載、網絡請求、資料庫操作、日志分析、記憶體管理以及洩漏檢測等,抽取一個BaseActivity出來,所有子類Activity都繼承它,指定每個類、方法、成員變量所注釋的要點。這可能會花費一定的時間,但磨刀不誤砍柴工,完善的架構為項目開發奠定良好的基礎。

二、注意代碼編寫規範

1、字元串的引用

Toast、Log、Dialog這些使用者互動提示常常用到字元串,有些開發者為了友善直接在使用地方寫上字元串,而沒有從strings.xml引用。這樣有一個明顯缺點:後續要修改字元串内容,需要到該檔案裡找到字元串才能對應修改。如果是統一從strings.xml引用字元串,那麼就能快速定位快速修改了。是以建議大家統一從strings.xml引用字元串。

2、尺寸與風格的引用

尺寸(dimension)與風格(style)一般是在xml檔案裡面用到,建議大家在dimens.xml配置各種尺寸,在styles.xml自定義風格,然後在xml檔案引用。原因與字元串引用一樣,可以快速定位修改。這隻是一個微小細節,也許對于多數開發者來說微不足道。但也就是衆多細節才構成龐大體系,規範應該從細節做起。

3、注意命名規範

命名應該通俗易懂,給别人看到類名、方法名或者變量名就知其用途的感覺,主要包括如下三點:

(1)包名、檔案夾、xml、drawable等單詞都是小寫,其中xml與drawable的命名單詞之間是下劃線連接配接;

(2)類名是每個單詞首字母大寫,後面小寫,遵循全駝峰規則;

(3)方法名、變量名是首個單詞全部小寫,後面的單詞首字母大寫,遵循駝峰規則;

三、警惕異常産生以及處理

1、空指針

有些if條件判斷需要加上空指針(null)判斷卻沒有做出對應判斷,造成抛出空指針異常,甚至導緻程式崩潰;有些if條件判斷不可能發生空指針卻加上判斷,多一個語句判斷,多一個指令周期,降低程式執行效率。那麼,需要開發者準确判斷是否有空指針發生的可能性,如果有就有必要加上空指針判斷。可能産生空指針的情景包括:從網絡請求資料解析成一個bean,該bean可能為null;使用new運算符來建立一個File,執行語句為new File(path),傳入參數path可能為null;從資料庫查詢傳回一個cursor對象,馬上調用cursor.moveToNext()方法,但是cursor可能為null。

        情景1:

直接使用bean-->   

String userName = loginBean.getName();
           

加上空指針判斷-->

String userName = loginBean != null ?loginBean.getName() : "";
           

       情景2:

直接使用path-->

File mFile = new File(path);
           

加上空指針判斷-->

if(path != null && !path.equals("")){
   File mFile = new File(path);
}
           

情景3:

直接使用cursor-->

while(cursor.moveToNext){
   ...
}
           

加上空指針判斷:

if(cursor == null)
   return;
while(cursor.moveToNext){
   ...
}
           

四、同步關鍵字的用法

同步關鍵字synchronized作用于變量(variable)時,變量的屬性應該是加上final。有時候變量使用到synchronized,前面卻沒有加上final修飾符,這樣使用android studio的lint靜态代碼檢測時就會提示synchronization on a non-final field。給出對應的解決方案是在變量前面加上final修飾符。

五、強制類型轉換

java語言允許強制類型轉換,開發者在不确定左右雙方類型是否一緻的情況下,往往加上強制類型轉換。這也就可能導緻沒必要的類型轉換,因為雙方的類型已經一緻。

比如:

View mView = (View) findViewById(R.id.my_view);
           

其實兩者類型已經都是View,那麼右邊的強制類型轉換變成多餘。這樣并不會導緻程式無法執行,隻是不夠簡潔。lint靜态代碼檢測時會提示Type conversion is redundant。

六、集合轉換成數組

使用toArray()把集合轉換成數組,應該傳入數組長度也就是集合的長度。自定義一個長度的做法是不恰當的。如果是傳入的數組長度小于實際長度,就無法完成轉換。

比如:

直接指定數組長度-->

List<String> var = entry.getValue();
String[] mArray = var.toArray(new String[5]);
           

正确做法是傳入集合長度-->

List<String> var = entry.getValue();
String[] mArray = var.toArray(new String[var.size()]);
           

七、String、StringBuffer與StringBuilder的正确使用

String通過“+”來拼接字元串,而StringBuilder是通過append()來拼接的。兩者的用法相信大家都很清楚,但有時會互相混淆,雖然不會影響程式執行,但是lint靜态代碼檢測時,會提示用法混亂。比如:隻需要用String就可以,卻用StringBuilder代替;StringBuilder裡面混合使用“+”來拼接。StringBuffer和StringBuidler都是用append來拼接比較複雜的字元串,但是靜态代碼檢測時,如果是單線程的情況下,會建議采用StringBuilder來代替StringBuffer,因為StringBuilder比StringBuffer效率要高。

情景1:

使用StringBuilder來做簡單字元串拼接-->

StringBuilder sb = new StringBuilder();
sb.append("群組").append(group.getGroupName());
           

使用String代替StringBuilder-->

String mGroup ="群組"+group.getGroupName();
           

情景2:

StringBuilder裡面混合使用“+”來拼接-->

StringBuilder sb = new StringBuilder();
sb.append("群聊(" + group.getGroupName() + ")建立成功");
           

應該是純append來拼接-->

StringBuilder sb = new StringBuilder();
sb.append("群聊(").append(group.getGroupName()).append(")建立成功");
           

八、if與switch的用法

if用作條件判斷,switch用于開關語句,兩者有共同點有時可以互相代替。但是判斷條件單一情況下,建議使用switch,這樣使得代碼結構清晰,可讀性強。

情景1:

使用if進行判斷-->

if (fileType.equals("wav")) {
            return R.drawable.filelook_icon_mp3;
        } else if (fileType.equals("mp3")) {
            return R.drawable.filelook_icon_mp3;
        } else if (fileType.equals("txt")) {
            return R.drawable.filelook_icon_txt;
        } else
            return R.drawable.filelook_icon_unknow;
           
}
           

使用switch代替-->

switch (fileType) {
            case "wav":
                return R.drawable.filelook_icon_mp3;
            case "mp3":
                return R.drawable.filelook_icon_mp3;
            case "txt":
                return R.drawable.filelook_icon_txt;
            default:
                return R.drawable.filelook_icon_unknow;
        }
           

最後,建議大家形成編寫規範代碼的習慣,良好的習慣從細節做起,讓習慣稱為自然。如果是采用Android Studio開發,可以使用Analyze導航欄裡面的lint進行靜态代碼檢測,裡面有各種規範限制,如果有不規範之處,會有相應提示,也給出相應的解決方法。

繼續閱讀