騰訊架構師教你如何寫出Android規(guī)范文檔
前言
一份合格的代碼不應只滿足于實現(xiàn)功能, 更應該遵循良好的規(guī)范. 遵循良好的代碼規(guī)范有利于:
- 提升程序穩(wěn)定性, 減少代碼隱患, 降低故障率;
- 增強可擴展性, 大幅提高維護效率;
- 統(tǒng)一標準, 提升多人協(xié)作效率;
- 方便新人快速上手, 在項目組人員發(fā)生變動時保證項目進度。
這里梳理一下Android開發(fā)過程中需要注意的一些地方, 包括多個部分, 另外根據(jù)約束力強弱分為兩類:
- 強制: 如果不遵守會導致代碼嚴重混亂, 后期維護復雜, 甚至會出現(xiàn)嚴重bug;
- 推薦: 如果不遵守可能會導致代碼描述不清, 理解困難, 導致功能越多維護越難的問題。
下面是規(guī)范正文
系統(tǒng)設計
強制:
- 不允許出現(xiàn)兩段相同的邏輯塊, 必須抽出為公共方法, 差異性使用參數(shù)控制, 避免修改時多處修改導致遺漏;
- 不允許出現(xiàn)兩段相同的處于同一邏輯組的復雜布局, 必須抽為單獨的include/merge;
- 不允許父類中出現(xiàn)子類具體方法, 如果需要的話可以父類定義抽象方法, 交由子類實現(xiàn);
- 不允許Activity內多Fragment之間的直接溝通, 必須通過Activity中轉。
推薦:
- 推薦使用MVP或者MVVM架構;
- 推薦使用Kotlin語言;
- 采用模塊分類方式替代文件類別方式, 方便快速查找模塊相關內容, 例: LoginActivity/LoginPreenter/LoginHttpRequest/LoginBean/LoginAdapter等所屬同一登錄模塊的文件放入一個文件夾, 而不是所有activity放入一個文件夾, 所有adapter放入一個文件夾。
命名方式
強制:
- 不允許出現(xiàn)中文命名方式;
- java/kotlin文件使用大駝峰方式, 例: LoginActivity.kt, NewsAdapter.kt, NewsBean.java;
- layout/drawable/anim/style等resource文件使用小寫+下劃線的方式, 例: login_activity.xml, login_logo.png;
- 類定義使用大駝峰方式, 例: class LoginPresenter {}, class NewsBean {};
- 對象使用小駝峰方式, 例: LoginPresenter loginPresenter, NewsBean newsBean;
- 靜態(tài)常量使用全大寫+下劃線的方式, 例: public static final boolean IS_RELESAE = true;
- Kotlin使用的布局中的控件id必須使用小駝峰方式, 例: android:id="@+id/tvLogin"。
推薦:
- 文件/資源命名時采用 模塊+類型 的方式, 以便迅速查找相關內容, 例如登錄頁面: LoginActivity.kt, login_activity.xml, login_logo.png, 網絡錯誤, #f3f3f3
- java使用的布局中的id名建議使用小駝峰方式, 并且使用控件類型縮寫開頭, 例: android:id="@+id/tvLogin", 附錄常用控件縮寫:
可見性
強制:
- 所有新定義的類/方法, 默認寫成private, 只有在其他類需要引用時再看情況標為public, protected, package-private;
推薦:
- java定義的父類中定義的方法如果子類重寫會導致問題時, 添加final關鍵字;
注釋相關
類/復雜或者不能從方法名字看出意圖的方法必須添加注釋, 當類/方法添加注釋時, 必須使用此類型注釋:
- /**
- * Created by XXX on 2019/6/19.
- * 描述此類作用, 邏輯復雜的說明一下主要思路
- */
- public class LoginPresenter {
- /**
- * 用于進行網絡請求
- * @params xxx XXX
- */
- public void doLoginRequest(...){}
- }
變量注釋不允許使用與類/方法一致的注釋形式;
方法注釋中不允許出現(xiàn)@params, @return的參數(shù)描述錯誤的情況, 必須實時更新;
推薦:
- 一段邏輯建議使用/* */的方式;
- 方法/參數(shù)建議添加 @Nullable, @NotNull, @UiThread 等注解;
代碼風格
- 此git目錄下同時存有 AndroidCodeStyleSetting.jar 配置文件, 用于AndroidStudio導入后按照統(tǒng)一風格進行代碼的格式化.
- 如果沒有編寫代碼時隨時格式化代碼的習慣, 可以在AndroidStudio版本控制提交窗口右側Before Commit中勾選Reformat code選項.
Android基本組件
強制:
- Intent通信時不允許傳遞超過1M的數(shù)據(jù), 可以采用外部Presenter中轉或者EventBus傳遞的方式;
- Intent隱式啟動時必須檢查目標是否存在, 否則會出現(xiàn)目標未找到崩潰: if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ ONLY) != null);
- Activity/Service/BroadcastReceiver內如果有耗時操作, 必須采用多線程進行處理;
- 應用內部發(fā)送廣播時, 只能使用LocalBroadcastManager.getInstance(this).sendBroadcast(intent), 不允許 context.sendBroadcast(intent), 避免外部應用攔截;
- 不允許在Application中緩存數(shù)據(jù), 全局的共享數(shù)據(jù)可以使用某presenter存儲, 或者使用SharedPreference讀寫;
- Activity或者Fragment中動態(tài)注冊BroadCastReceiver時,registerReceiver和unregisterReceiver必須要成對出現(xiàn);
推薦:
- Activity#onPause/onStop中結合isFinishing的判斷來執(zhí)行資源的釋放, 必免放在執(zhí)行時機較晚的Activity#onDestroy()中執(zhí)行;
- 不要在Activity#onPause中執(zhí)行耗時操作, 這樣會導致界面跳轉卡頓, 可以放入Activity#onStop中執(zhí)行;
UI/布局
強制:
- 布局xml優(yōu)先使用ConstraintLayout, 可以保證無嵌套的情況下完成包括部分控件同時顯隱需求在內的99%的布局要求;
- 不允許使用ScrollView包裹ListView/GridView/ExpandableListVIew等列表View, 復雜多項式列表可以使用多ItemType進行處理;
推薦:
- 在Activity中顯示對話框或彈出浮層時, 盡量使用DialogFragment, 而非Dialog/AlertDialog, 便于隨Activity生命周期管理彈窗的生命周期;
進程/線程/消息推送
強制:
- 存在多進程的情況時, Application中的初始化代碼要根據(jù)進程分別處理, 避免初始化不必要的業(yè)務;
- 新建線程時, 必須通過線程池的方式, 不允許采用new Thread()的方式;
- Activity/Fragment中使用Handler時, 必須使用靜態(tài)內部類+WeakReferences方式或者在onStop中調用handler.removeCallbacksAndMessages;
推薦:
- 多進程間共享數(shù)據(jù)使用ContentProvider替代SharedPreferences#MODE_MULTI_PROCESS;
文件/數(shù)據(jù)庫
強制:
- 使用系統(tǒng)API獲取文件路徑, 避免手拼字符串, 例: android.os.Environment#getExternalStorageDirectory(), Context#getFilesDir(), 錯誤示例: File file = new File("/mnt/sdcard/Download/Album", name);
- 當使用外部存儲時, 必須檢查外部存儲的可用性: Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
- 數(shù)據(jù)庫Cursor使用之后必須關閉, 以免內存泄漏;
推薦:
SharedPreference僅存儲簡單數(shù)據(jù)類型, 不要存儲復雜數(shù)據(jù), 如json數(shù)據(jù)/Bitmap編碼等;
SharedPreference提交數(shù)據(jù)時, 盡量使用Editor#apply(), 而非Editor#commit();
圖片/動畫
強制:
- 加載大圖時必須在子線程中處理, 否則會卡UI;
- 在Activity.onPause()/onStop()中關閉當前activity正在執(zhí)行的動畫;
推薦:
- Android圖片建議轉化為WebP格式, 可以減少APK體積;
- 動畫盡量不要使用AnimationDrawable, 占用非常多內存;
- 使用ARGB_565代替ARGB_888, 減少內存占用;
- 當Animation執(zhí)行結束時, 調用View.clearAnimation()釋放相關資源;
安全性
強制:
- 上線包必須混淆;
- 加解密的秘鑰/鹽不允許硬編碼到代碼中, 以防反編譯獲取;
- Https處理時必須校驗證書, 不允許直接接受任意證書;
- 使用Android的AES/DES/DESede加密算法時, 不要使用默認的加密模式ECB, 應顯示指定使用CBC/CFB加密模式;
- 禁止把敏感信息打印到log中;
- 在應用發(fā)布時必須確保android:debuggable為false;
- 必須利用X509TrustManager子類中的checkServerTrusted函數(shù)效驗服務器端證書的合法性,
- 必須將android:allowbackup屬性設置為false, 防止adb backup導出應用數(shù)據(jù)。