Android開發規範

註釋

類/複雜或者不能從方法名字看出意圖的方法必須添加註釋java

/**
 * @Author: LiuJinYang
 * @CreateDate: 2020/5/16 9:32
 * 網絡請求工具類
 */
public class RetrofitUtil {
    /**
     * 添加公參basic
     *
     * @param key 公參字段名
     * @param value 公參值
     */
    public void addBasic(String key, String value) {
        basicMap.put(key, value);
    }
}
複製代碼

命名

  • 類命名,類文件名使用 UpperCameCase 風格, 必須聽從駝峯形式, 且要保證從類的名稱上能區分出它是什麼功能類型;
  • 方法名第一個單詞要體現出方法的功能 例如: save, set, get, insert, create;
  • 對象使用小駝峯方式, 例: LoginPresenter loginPresenter, NewsBean newsBean;
  • 全局變量和局部變量功能相同時:全局加 「m」。

參數名,能夠和成員變量名相同,但要注意引用成員變量時,須要加上 this 字段android

  • 常量:所有大寫,單詞之間使用 「_」 分隔。
  • 代碼中的命名嚴禁使用拼音與英文混合的方式,更不容許直接使用中文方式;

正確的英文拼寫和語法可讓閱讀者易於理解, 避免歧義。純拼音命名方式也不要使用。算法

  • 抽象類命名使用 Abstract 或者 Base 開頭,異常類命名使用 Exception 結尾;測試類以他要測試的類的名稱開始,以 Test 結束。

資源文件命名

  1. layout文件命名:
Activity 的 layout 以 module_activity 開頭
Fragment 的 layout 以 module_fragment 開頭
Dialog 的 layout 以 module_dialog 開頭
include 的 layout 以 module_include 開頭
ListView 的行 layout 以 module_list_item 開頭
RecyclerView 的 item layout 以 module_recycle_item 開頭
GridView 的 item layout 以 module_grid_item 開頭
複製代碼
  1. drawable命名:

模塊名_業務功能描述_控件描述_控件狀態限定詞, 如:module_login_btn_pressed,module_tabs_icon_home_normal數據庫

  1. anim 命名:

模塊名_邏輯名稱_[方向|序號],如 module_fade_in , module_fade_out , module_push_down_in緩存

  1. color命名:

模塊名_邏輯名稱_顏色,如: #33b5e5e5安全

  1. dimen 命名:

模塊名_描述信息,如:1dp性能優化

  1. string 命名:

模塊名_邏輯名稱,如:moudule_login_tips,module_homepage_notice_descmarkdown

  1. id 命名:

推薦使用小寫字母並用下劃線進行分割,View 組件的資源 id 建議以 View 的縮寫做爲前綴。經常使用縮寫表以下:網絡

LinearLayout  ll
RelativeLayout  rl
ConstraintLayout  cl
ListView  lv
ScollView  sv
TextView  tv
Button  btn
ImageView  iv
CheckBox  cb
RadioButton  rb
EditText  et
複製代碼

Android 基本組件

Android 基 本 組 件 指 Activity 、 Fragment 、 Service 、 BroadcastReceiver 、ContentProvider 等等。session

  1. Activity 間的數據通訊, 對於數據量比較大的,避免使用 Intent + Parcelable的方式,能夠考慮 EventBus/RxBus 等替代方案,以避免形成 TransactionTooLargeException。

  2. Activity 間經過隱式 Intent 的跳轉,在發出 Intent 以前必須經過 resolveActivity檢查,避免找不到合適的調用組件,形成 ActivityNotFoundException 的異常。

  3. 避免在 Service#onStartCommand()/onBind()方法中執行耗時操做,若是確

實有需求,應改用 IntentService 或採用其餘異步機制完成。

  1. 避免在 BroadcastReceiver#onReceive()中執行耗時操做,若是有耗時工做,

應該建立 IntentService 完成,而不該該在 BroadcastReceiver 內建立子線程去作。

  1. 避免使用隱式 Intent 廣播敏感信息,信息可能被其餘註冊了對應

BroadcastReceiver 的 App 接收。

  1. 對於只用於應用內的廣播,優先使用 LocalBroadcastManager 來進行註冊

和發送,LocalBroadcastManager 安全性更好,同時擁有更高的運行效率。

  1. Activity或者Fragment中動態註冊BroadCastReceiver時,registerReceiver()

和 unregisterReceiver()要成對出現。

  1. 不要在 Activity#onDestroy()內執行釋放資源的工做,例如一些工做線程的

銷燬和中止,由於 onDestroy()執行的時機可能較晚。可根據實際須要,在Activity的onPause()/onStop()中結合 isFinishing()的判斷來執行。

  1. 當前 Activity 的 onPause 方法執行結束後纔會建立(onCreate)或恢復

(onRestart)別的 Activity,因此在 onPause方法中不適合作耗時較長的工做,這會影響到頁面之間的跳轉效率。

  1. Service 須要以多線程來併發處理多個啓動請求,建議使用 IntentService,

可避免各類複雜的設置。

UI 與佈局

  • 佈局xml優先使用ConstraintLayout, 能夠保證無嵌套的狀況下完成包括部分控件同時顯隱需求在內的99%的佈局要求;
  1. 佈局中不得不使用 ViewGroup 多重嵌套時,不要使用 LinearLayout 嵌套,

改用 RelativeLayout,能夠有效下降嵌套數。

  1. 在 Activity 中顯示對話框或彈出浮層時,儘可能使用 DialogFragment,而非

Dialog/AlertDialog,這樣便於隨Activity生命週期管理對話框/彈出浮層的生命週期。

  1. 禁止在非 UI 線程進行 View 相關操做。

  2. 禁止在設計佈局時屢次爲子 View 和父 View 設置一樣背景進而形成頁面過

度繪製,推薦將不須要顯示的佈局進行及時隱藏。

  1. 不能使用 ScrollView 包裹 RecyclerView/ListView/GridView/ExpandableListVIew;由於這

樣會把 ListView 的全部 Item 都加載到內存中,要消耗巨大的內存和 cpu 去繪製圖面。

  1. 不要在 Android 的 Application 對象中緩存數據。基礎組件之間的數據共享

請使用 Intent 等機制,也可以使用 SharedPreferences 等數據持久化機制。

  1. 使用 Adapter 的時候,若是你使用了 ViewHolder 作緩存,在 getView()的

方法中不管這項 convertView 的每一個子控件是否須要設置屬性(好比某個 TextView 設置的文本可能爲 null,某個按鈕的背景色爲透明,某控件的顏色爲透明等),都需 要爲其顯式設置屬性(Textview 的文本爲空也須要設置 setText(""),背景透明也須要 設置),不然在滑動的過程當中,由於 adapter item 複用的緣由,會出現內容的顯示錯 亂。

進程、線程與消息通訊

  1. 不要經過 Intent 在 Android 基礎組件之間傳遞大數據(binder transaction

緩存爲 1MB),可能致使 OOM。

  1. 在 Application 的業務初始化代碼加入進程判斷,確保只在本身須要的進程

初始化。特別是後臺進程減小沒必要要的業務初始化。

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        //在全部進程中初始化
        ....
        //僅在主進程中初始化
        if (mainProcess) {
            ...
        }
        //僅在後臺進程中初始化
        if (bgProcess) {
            ...
        }
    }
}
複製代碼
  1. 新建線程時,必須經過線程池提供(AsyncTask 或者 ThreadPoolExecutor

或者其餘形式自定義的線程池),不容許在應用中自行顯式建立線程。

  1. 線程池不容許使用 Executors 去建立,而是經過 ThreadPoolExecutor 的方

式,這樣的處理方式讓寫的同窗更加明確線程池的運行規則,規避資源耗盡的風險。

  1. 子線程中不能更新界面,更新界面必須在主線程中進行,網絡操做不能在

主線程中調用。

  1. 新建線程時,定義能識別本身業務的線程名稱,便於性能優化和問題排查。
public class MyThread extends Thread {
    public MyThread(){
        super.setName("ThreadName");
        …
    }
}
複製代碼
  1. ThreadPoolExecutor 設置線程存活時間(setKeepAliveTime),確保空閒時

線程能被釋放。

  1. 禁 止 在 多 進 程 之 間 用 SharedPreferences 共 享 數 據 , 雖 然 可 以(MODE_MULTI_PROCESS,已過期),但官方已不推薦。

  2. 謹慎使用 Android 的多進程,多進程雖然可以下降主進程的內存壓力,但

會遇到以下問題: 1) 首次進入新啓動進程的頁面時會有延時的現象(有可能黑屏、白屏幾秒,是白屏仍是黑屏和新 Activity 的主題有關); 2) 應用內多進程時,Application實例化屢次,須要考慮各個模塊是否都須要在全部進程中初始化。

文件與數據庫

  1. 任什麼時候候不要硬編碼文件路徑,請使用 Android 文件系統 API 訪問。

  2. 當使用外部存儲時,必須檢查外部存儲的可用性。

  3. 應用間共享文件時,不要經過放寬文件系統權限的方式去實現,而應使用

FileProvider。

  1. SharedPreference 中只能存儲簡單數據類型(int、boolean、String 等),

複雜數據類型建議使用文件、數據庫等其餘方式存儲。

  1. 數據庫 Cursor 必須確保使用完後關閉,以避免內存泄漏。

  2. 多線程操做寫入數據庫時,須要使用事務,以避免出現同步問題。

  3. 執行 SQL 語句時,應使用 SQLiteDatabase#insert()、update()、delete(),

不要使用 SQLiteDatabase#execSQL(),以避免 SQL 注入風險。

  1. 若是 ContentProvider 管理的數據存儲在 SQL 數據庫中,應該避免將不受

信任的外部數據直接拼接在原始 SQL 語句中。

Bitmap、Drawable 與動畫

  1. png 圖片使用 TinyPNG 或者相似工具壓縮處理,減小包體積。

  2. 使用完畢的圖片,應該及時回收,釋放寶貴的內存。

Bitmap bitmap = null;
loadBitmapAsync(new OnResult(result){
    bitmap = result;
});
...使用該 bitmap...
// 使用結束,在 2.3.3 及如下須要調用 recycle()函數,在 2.3.3 以上 GC 會自動管理,除非你明確不須要再用。
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
    bitmap.recycle();
}
bitmap = null;
複製代碼
  1. 在 Activity#onPause()或 Activity#onStop()回調中,關閉當前 activity 正在執行的的動畫。
public void onPause() {
    //頁面退出,及時清理動畫資源
    mImageView.clearAnimation()
}
複製代碼
  1. 在動畫或者其餘異步任務結束時,應該考慮回調時刻的環境是否還支持業

務處理。例如 Activity 的onStop() 函數已經執行, 且在該函數中主動釋放了資源, 此時回調中若是不作判斷就會空指針崩潰。

  1. 使用 RGB_565 代替 RGB_888,在不怎麼下降視覺效果的前提下,減小內

存佔用。

  1. 大圖片資源不要直接打包到 apk,能夠考慮經過文件倉庫遠程下載,減少包

體積。

  1. 當 View Animation 執行結束時,調用View.clearAnimation()釋放相關資源。

安全

  1. 將 android:allowbackup 屬性必須設置爲 false,阻止應用數據被導出。

  2. 若是使用自定義 HostnameVerifier 實現類,必須在 verify()方法中校驗服務

器主機名的合法性,不然可能受到中間人攻擊;若是使用自定義X509TrustManager 實現類,必須在 checkServerTrusted()方法中校驗服務端證書的合法性,不然可能受到中間人攻擊。

HostnameVerifier hnv = new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        if("yourhostname".equals(hostname)){
            return true;
        } else {
            HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
            return hv.verify(hostname, session);
        }
    }
};
複製代碼
  1. 在 SDK 支持的狀況下,Android 應用必須使用 V2 簽名,這將對 APK 文

件的修改作更多的保護。

  1. 全部的 Android 基本組件(Activity、Service、BroadcastReceiver、

ContentProvider 等)都不該在沒有嚴格權限控制的狀況下,將android:exported 設置爲 true。

  1. WebView 應設置 WebView#getSettings()#setAllowFileAccess(false)、

WebView#getSettings()#setAllowFileAccessFromFileURLs(false) 、 WebView#getSettings()#setAllowUniversalAccessFromFileURLs(false),阻止 file scheme URL 的訪問。

  1. 不要把敏感信息打印到 log 中。

  2. 確保應用發佈版本的 android:debuggable 屬性設置爲 false。

  3. 本地加密祕鑰不能硬編碼在代碼中,更不能使用 SharedPreferences 等本

地持久化機制存儲。應選擇 Android自身的祕鑰庫(KeyStore)機制或者其餘安全 性更高的安全解決方案保存。

  1. addJavascriptInterface() 能夠添加 JS 對本地 Java 方法的調用,但這自己

會致使惡意代碼的攻擊。在 Android 4.2(API Level 17)如下, 不該再使用這樣的調用方式。在 Android 4.2 及以上, 須要對本地被遠程調用的方法顯式添加@JavascriptInterface annotation。

  1. 使用 Android 的 AES/DES/DESede 加密算法時,不要使用 ECB 加密模式,

應使用 CBC 或 CFB 加密模式; MD5 和 SHA-一、SHA-256 等經常使用算法是 Hash 算法,有必定的安全性,但不能代替加密算法。敏感信息的存儲和傳輸,須要使用專業的加密機制。

加密模式有 ECB、CBC、CFB、OFB 等,其中 ECB 的安全性較弱,若是使用固
定的密鑰,相同的明文將會生成相同的密文,容易受到字典攻擊,建議使用 CBC、
CFB 或 OFB 等模式。
1)  ECB:Electronic codebook,電子密碼本模式
2)  CBC:Cipher-block chaining,密碼分組連接模式
3)  CFB:Cipher feedback,密文反饋模式
4)  OFB:Output feedback,輸出反饋模式
複製代碼
  1. Android APP 在 HTTPS 通訊中,驗證策略須要改爲嚴格模式。

  2. 在 Android 4.2(API Level 17)及以上,對安全性要求較高的應用可在 Activity中,對 Activity 所關聯的 Window 應用 WindowManager.LayoutParams.FLAG_SECURE, 防止被截屏、錄屏。但要注意的是,一個 Activity 關聯的 Window 可能不止一個,若是使用了 Dialog / DialogFragment 等控件彈出對話框,它們自己也會建立一個新的 Window,也同樣須要保護。

系統設計

  1. 不容許出現兩段相同的邏輯塊, 必須抽出爲公共方法, 差別性使用參數控制, 避免修改時多處修改致使遺漏;

  2. 不容許出現兩段相同的處於同一邏輯組的複雜佈局, 必須抽爲單獨的include/merge;

  3. 不容許Activity內多Fragment之間的直接溝通, 必須經過Activity中轉;

  4. 採用模塊分類方式替代文件類別方式, 方便快速查找模塊相關內容, 例: LoginActivity/LoginPreenter/LoginHttpRequest/LoginBean/LoginAdapter等所屬同一登陸模塊的文件放入一個文件夾, 而不是全部activity放入一個文件夾, 全部adapter放入一個文件夾。

  5. 全部新定義的類/方法, 默認寫成private, 只有在其餘類須要引用時再看狀況標爲public, protected, package-private;

  6. java定義的父類中定義的方法若是子類重寫會致使問題時, 添加final關鍵字;

其餘

  1. 不能使用 System.out.println 打印 log。

  2. Log 的 tag 不能是" "。

  3. 項目創建REWADME.md文件,書寫版本迭代中較重要的修改,包括需求修改,代碼修改,三方庫引用等;

參考資料

阿里巴巴 Android 開發手冊

我是今陽,若是想要進階和了解更多的乾貨,歡迎關注公衆號」今陽說「接收個人最新文章
相關文章
相關標籤/搜索