• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • Android 項目代碼質量保證實踐

    發表于:2019-07-24來源:簡書作者:zyl06點擊數: 標簽:Android
    一個項目開發必然會涉及團隊協作,而工程質量就需要團隊去保證。一般我們期望的代碼:無潛在風險、無重復邏輯、風格無差異、可閱讀性好、新人上手速度快等。為了達到上述目標

    1 背景

    一個項目開發必然會涉及團隊協作,而工程質量就需要團隊去保證。一般我們期望的代碼:無潛在風險、無重復邏輯、風格無差異、可閱讀性好、新人上手速度快等。為了達到上述目標,一般團隊都會制定一套自己認可的編碼規范,并且周期性進行 code review。然而編碼規范的制定,那么一套編碼規范需要包含哪些內容,另外編碼規范僅僅是一套軟規范,實際程序員同學能遵守到什么程序還是一個未知數,所以需要我們進行人肉 code review,而這種人肉排查方式,很容易遺漏部分問題,保障性還是有些不足。
    為此,我們從編碼前期、編碼中期和編碼后期保證進行了初步嘗試。

    2 編碼前期 - 編碼規范

    對于一個 Android 項目,一般需要涉及的編碼規范有:
    1. 普通 java 編碼風格規范
      如每個方法最大行數,每個類文件的最大行數,每個方法最大參數數等
    2. 普通 java 編碼最佳實踐
      if、for、try 等嵌套深度規范,變量初始化規范等
    3. 通用 Android 編碼規范(java 部分和 xml 部分),
      包含 Android java 部分和 Android xml 部分,如避免使用普通內部類定義handler,避免 layout xml 中存在無用結點等
    4. Gradle 編碼規范
      如盡量避免 lib 使用 module,獨立工程可以通過 aar 或 mvn 方式導入
    5. 具體項目相關的編碼規范等
      如項目團隊規定使用自定義 LogUtil 打日志,Activity、Fragment 等重要類的繼承關系,Activity 對應的 xml 文件必須以 activity_ 開頭等
    制定了這些內容可以一定程度上規范程序猿的編碼,配合團隊進行了周期性的 code review (一般是一個版本一次,大概 4 個星期一次),會有比較好的效果。然而即使這么做,還是存在一定的問題,距離我們期望的目標還是比較遠。比如各個單例類的定義五花八門,使用 LogUtil 代替 Log 的使用,Message.Obtain() 代替 new Message(),Activity 部分文件命名,甚至 Activity、Fragment 的基類定義規則還是很容易發生錯誤,并沒有被發現。隨著編碼規范的完善充實,多個開發的編碼規范如何保證,就會成為一個顯而易見的問題。

    3 編碼中期 - 編碼模板

    為了實現公用代碼復用,我們定義了一些 util 工具類,但隨著各個開發的補充,這套 util 工具類也越來越多,如 LogUtil、KeyboardUtil 等,而這些類一部分是為了統一入口,如統一使用 LogUtil,可以統一做到測試服打開本地日志,線上服關閉日志;KeyboardUtil 方便使用者控制鍵盤的彈出隱藏等操作。雖然定義了這些工具類,但終究存在應該使用而沒有使用的情況。當然這些工具代碼并不難,開發在自己的模塊也能很容易的實現和使用,一般也不會出問題。然而上述講的優點都會消失掉。而這些問題依賴 code review 也是件頭疼的問題。
    此外,RecycleView 的編碼方式,單例模式的實現方式等等,各個開發可能寫出各式代碼,甚至實現的單例模式并不是線程安全的。
    提了這么多,另一方面,要求開發在繁忙的業務中嚴格遵守這些規范,也有些強人所難。所幸,Android Studio 為我們提供了編碼模板來解放開發的工作,并一定程度上統一編碼風格。

    3.1 Live Template

    3.1.1 系統模板

    查看一個使用 Android Studio 中很常見的例子,輸入 for,出現下拉列表如下:
     
    image
    當選擇 fori,出現編碼片段:
     
    image
    確認循環變量 i,跳入循環結果值的輸入:
     
    image
    上例,就是 Android Studio 中系統提供的 Live Template 一個實例。這個類似于 iOS 中的 Code Snippets,提供了代碼片段的能力。
    Android Studio (Mac) 進入 Settings/Preferences -> Editor -> Live Templates,可以看到已定義的模板組:
     
    image
    查看 fori 編碼模板的實現:
     
    image
    • A: 完成模板的快捷鍵 Tab
    • B: 位置分類 iterations
    • C: 編碼模板對應的縮寫 fori
    • D: 模板的內容
    • E: 模板應用環境

    3.1.2 自定義模板

    1. 構建項目 group
       
      image
      輸入 group 的名稱
       
      image
    2. 構建具體編碼模板
       
      image
      • Abbreviation:觸發編碼模板的縮寫
      • Description:模板的具體描述
      • Template Text:具體的模板內容
    3. 變量定義
      變量形式為 $<variable_name>$,點擊 Edit variables 可設置變量具體內容:
       
      image
    4. Name:變量名
    5. Expression:變量表現
    6. Default value:默認值
    7. Skip if defined:是否跳過編輯已經定義的值
    8. 模板應用環境
      點擊 No application contexts yet. Define,設置為 java 環境:
       
      image
    9. 模板文件
      構建了模板 group 后,在 android studio config\templates 目錄下查看到 yanxuan.xml。
      windows: C:\Users\\<user>\\.AndroidStudiox.x\config\templates(user 為你的計算機用戶名)
      mac:~/Library/Preferences/AndroidStudiox.x/templates
      <templateSet group="test"> <template name="yxtest" value="testMethod($a$, $b$);" description="這是一個測試模板" toReformat="false" toShortenFQNames="true"> <variable name="a" expression="lineNumber()" defaultValue="2" alwaysStopAt="false" /> <variable name="b" expression="" defaultValue="" alwaysStopAt="true" /> <context> <option name="JAVA_CODE" value="true" /> <option name="JAVA_STATEMENT" value="true" /> <option name="JAVA_EXPRESSION" value="true" /> <option name="JAVA_DECLARATION" value="true" /> <option name="JAVA_COMMENT" value="true" /> <option name="JAVA_STRING" value="true" /> <option name="COMPLETION" value="true" /> </context> </template> </templateSet> 
    10. 設置完畢,實踐查看:
       
      image
      yxtest
       
      image
      singleton

    3.2 Android Studio Template

    1. 背景
      除了 Live Template 之外,工程項目中很多新建的類也有很多機械的代碼,如我們定義的 Activity 要么繼承自 BaseBlankActivity,要么繼承自 BaseActionBarActivity,另外項目中采用 MVP 模式,因此一個 Activity 基本上會有一個對應的 presenter 類,一個 layout 文件,同時很多時候,一個頁面中會有一個需要支持刷新的 RecycleView 等。除此之外,ViewHolder、HttpTask 等代碼也是固定模式的代碼。
      這些都是固定機械的代碼,而如果是人肉去寫的話,難免會出現代碼風格不一致、不規范的情況,同時也浪費了一部分的時間。所幸,Android Studio 提供了工程類模板,方便我們實現這樣的功能。
    2. 系統模板
      查看 Android Studio 系統類模板,我們能發現有很多定義好的類模板:
       
      image
      如需要創建一個空的 Activity 頁面,可以選擇 Empty Activity,并填寫類名,layout 名稱等信息,之后就能出現對應的添加或修改:MainActivity.java、activity_main.xml、AndroidManifest.xml
       
      image
      而這些模板定義,可以在相關路徑文件中找到:
      < >Windows: ${Android Studio 的安裝目錄}/plugins/android/lib/templates/Mac: Android Studio.app/Contents/plugins/android/lib/templates/
    image
    針對 EmpytActivity 這里需要定義的文件有:
    < >globals.xml.ftl:定義當前模板的一些全局變量recipe.xml.ftl:定義模板拷貝的邏輯等template.xml:定義模板對話框的樣式template_blank_activity.png:定義模板的圖標root/src/app_package/SimpleActivity.java.ftl:具體的模板文件
    image16
    圖片來自:http://www.slideshare.net/murphonic/custom-android-code-templates-15537501
    • 自定義模板
      而針對我們需要自定義的模板,可以在模板定義路徑下新建文件夾和文件即可,細節內容可查看 Tutorial How To Create Custom Android Code Templates
      項目的模板文件內容:
       
      image17
      設置完模板文件之后,重啟 Android Studio,可以生效模板文件,使用模板文件如下:
       
      image18

    4 編碼后期 - 靜態代碼檢查

    由上,我們定義了編碼規范,定義了 Live Template 和 Android Studio Template 方便程序猿更好的準守我們的項目編碼規范。然后編碼規范畢竟只是軟規范,而提供編碼模板更多的解決大量 util 的使用問題和便利小伙伴完成機械編碼,并不能完全保證程序猿嚴格按照全部的規范來編碼。
    為此,我們需要一套靜態代碼檢查機制能檢查已有的代碼是否遵守規范??偨Y已有的規范,可以將規范類型歸納為普通 Java 規范、普通 Android 規范、具體項目規范等。而這些檢查點,可以配合不同的檢查工具進行檢查。

    4.1 檢查 java 代碼風格 - CheckStyle

    對于 java 規范,checkstyle 幫助開發者實現常用的檢查。這里 CheckStyle 能檢查的內容有:
    1. Javadoc 注釋
    2. 命名約定
    3. 標題
    4. Import 語句
    5. 體積大小
    6. 空白
    7. 修飾符
    8. 代碼問題
    9. 類設計
    10. 混合檢查(包活一些有用的比如非必須的System.out和printstackTrace)
    檢查內容很多,而檢查項需要和具體的項目規范做結合。如,每行代碼字符數控制在 80,單頁代碼行數控制在 800 等。因此需要結合配置文件,來檢查項目中的 java 代碼。在 Android Studio 上配置 CheckStyle 流程如下:
    1. 在 Android Studio 中添加 gradle Plugin
      apply plugin: 'checkstyle' 
    2. 設置 CheckStyle 版本
      checkstyle { toolVersion '6.1.1' showViolations true } 
    3. 配置 CheckStyle 檢查項
      task checkstyle(type: Checkstyle) { configFile file("$configDir/checkstyle/checkstyle.xml") configProperties.checkstyleSuppressionsPath = file("$configDir/checkstyle/suppressions.xml").absolutePath source 'src' include '**/*.java' // 檢查 java 代碼 exclude '**/gen/**' // 排除生成的代碼 classpath = files() ignoreFailures true // 忽略檢查失敗的情況,避免gradle命令執行中止 } 
    4. 配置自定義的檢查項:
      checkstyle.xml
      <!--單個文件方法數上限最多為 30--> <module name="MethodCount"> <property name="maxTotal" value="30"/> </module> <!--方法名的首字母是小寫--> <module name="MethodName"> <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> </module> <!--靜態變量名的首字符是 s--> <module name="StaticVariableName"> <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> <property name="applyToPublic" value="true"/> <property name="applyToProtected" value="true"/> <property name="applyToPackage" value="true"/> <property name="applyToPrivate" value="true"/> </module> <!--只有私有構造函數的類需要定義成 final 類型--> <module name="FinalClass"/> ... 
      具體其他的檢查項配置可以查看 檢查配置鏈接
    5. 執行 checkstyle 檢查
      ./gradlew checkstyle 
    6. 查看檢查結果
      命令執行結束,查看檢查結果文件:${project}/app/build/reports/checkstyle/checkstyle.html
       
      image

    4.2 檢查 java 代碼質量 - FindBugs

    CheckStyle 工具不同的是,FindBugs 不注重樣式或者格式,而是試圖尋找出真正的缺陷或者現在的性能問題。FindBugs 檢查類和 Jar 文件,不是通過分析類文件的形式或結構來分析程序,而是使用 Visitor 模式,將字節碼與一組缺陷模式進行對比以發現可能的問題。而這些問題比如如下:
    1. 忽略返回值
       
      image
      上述代碼執行結束之后,并沒有什么意義,變量 a 的值也不會變成 dddbbbccc。因此,上述代碼很可能是程序猿的 bug。為此 FindBugs 能找出這種問題
    2. 空指針示例
       
      image
      上述最后一行代碼,很明顯在執行的時候會發生空指針異常,這里因為 FindBugs 無法知道變量 strMaps 是否確實有 aaa 這個 key,為此這里會檢查出錯誤。
    3. 未初始化的成員變量使用
       
      image
      這里由于類成員變量 actions 并未初始化,因此當 actions.add("TEST") 被執行的時候會發生異常。
    Android Studio 上 FindBugs 的集成如下:
    1. 在 gradle 中引入插件
      apply plugin: 'findbugs' 
    2. 在 gradle 中配置 findbugs task
      task findbugs(type: FindBugs, dependsOn: "assembleDebug") { ignoreFailures = false effort = "max" reportLevel = "high" excludeFilter = new File("$configDir/findbugs/findbugs-filter.xml") classes = files("${project.rootDir}/app/build/intermediates/classes") source 'src' include '**/*.java' exclude '**/gen/**' reports { xml.enabled = false html.enabled = true xml { destination "$reportsDir/findbugs/findbugs.xml" } html { destination "$reportsDir/findbugs/findbugs.html" } } classpath = files() ignoreFailures true // 避免檢查失敗 gradle 執行中止 } 
    3. 執行 findbugs 檢查
      ./gradlew findbugs 
    4. 查看檢查結果
      查看檢查結果文件:${project}/app/build/reports/findbugs/findbugs.html
       
      image

    4.3 檢查 Android 代碼質量 - Lint

    4.3.1 基本介紹

    前面 FindBugs 的檢查實例(忽略返回值, 未初始化的成員變量使用),可以發現在 Android Studio IDE 上,已經出現了標黃提示,我們把光標放上去,就能看到具體的提示了:
     
    image
    cmd + F1 可以看到具體的錯誤提示:
     
    image
    這就原生 Lint 給我們提供的錯誤提示功能。除了和 FindBugs 重復的純 java 代碼檢查之外,Lint 能檢查很多其他工具無法檢查的內容,也更貼合 Android:
     
    image
    在 Activity 內定義非靜態內部類 Handler 的報警
     
    image
    AndroidManifest.xml 中定義 export 為 true 的廣播接受器,但沒有定義權限,Lint 檢查認為是不安全的
     
    image
    build.gradle 文件中引用的 support 包的版本低的提示
    Android Lint 是一個靜態代碼檢查工具,能夠對潛在的 bug,可能的安全性、性能、可用性、可訪問性、國際化等優化內容做出監測:
    image
    image
    來自官方文檔 Improve Your Code with Lint
    1. App Source Files:工程中的源文件,包括 java 代碼、資源 xml 代碼、gradle 文件,圖片資源文件以及 progroud 等文件
    2. lint.xml:配置文件,配置哪些 lint 檢查可以排除,自定義問題的嚴重級別
    3. lint Tool:靜態代碼檢查工具,可以是命令行或者集成在 Android Studio 上
    4. lint Output:代碼檢查結果,可以直接顯示在 Console 上,也可以是 lint-result.html

    4.3.2 原生 Lint 檢查

    在 Android SDK Tools 16 及更高的版本中,Lint 工具會自動安裝。原生 Lint 的檢查項已經有 200 多項 (包括前面示例的 5 項內容),因此使用原生的功能點,就能檢查開發中的大部分通用問題。
    1. Android Studio IDE 上配置 Lint 檢查偏好設置
      (Mac 下) PreferencesEditorInspections 進入 Android StudioLint 配置界面
       
      image
      • A:配置 Profile,方便不同項目或者不同情況下使用不同的 Profile 進行檢查
      • B:Lint 檢查點 Group
      • C:Lint 檢查點具體描述
      • D:Lint 檢查點警告級別設置
      • E:Lint 檢查點開關
    2. lint.xml 上配置 Lint
      除了可以通過 IDE 配置 Lint,還可以通過直接 lint.xml 為單個項目配置檢查規則
      <?xml version="1.0" encoding="UTF-8"?> <lint> <!-- Disable the given check in this project --> <issue id="IconMissingDensityFolder" severity="ignore" /> <!-- Ignore the ObsoleteLayoutParam issue in the specified files --> <issue id="ObsoleteLayoutParam"> <ignore path="res/layout/activation.xml" /> <ignore path="res/layout-xlarge/activation.xml" /> </issue> <!-- Ignore the UselessLeaf issue in the specified file --> <issue id="UselessLeaf"> <ignore path="res/layout/main.xml" /> </issue> <!-- Change the severity of hardcoded strings to "error" --> <issue id="HardcodedText" severity="error" /> </lint> 
      來源 Android Develop 文檔 Improve Your Code with Lint
    3. gradle 中配置 Lint task
      android { lintOptions { abortOnError false // 配置 lint 過程中出錯,不中止 gradle 任務 xmlReport false htmlReport true lintConfig file("$configDir/lint/lint.xml") // 配置 lint 檢查規則 htmlOutput file("$reportsDir/lint/lint-result.html") // 配置 lint 輸出文件 xmlOutput file("$reportsDir/lint/lint-result.xml") // 配置 lint 輸出文件 } } 
    4. 執行檢查
      在工程根目錄執行以下命令 (Mac),以執行檢查任務
      ./gradlew lint 
    5. 檢查結果
      生成的檢查結果在 ${項目工程}/app/build/reports/lint/lint-result.html
       
      image

    4.3.3 自定義 Lint 檢查

    雖然原生的 Lint 檢查已經很強大了,檢查項也已經很多,然而還是無法滿足項目中的特有需求
    1. log 統一使用 LogUtil
    2. 對應 Activity 的 layout 命名為 activity_XXX
    3. 對應 Fragment 的 layout 命名為 fragment_XXX
    4. Activity 必須派生自 BaseBlankActivityBaseActionBarActivity
    對于以上這些需求,原生 Lint 檢查(包括 CheckStyle,FindBugs)就已經無能為力了,我們必須編碼支持自定義檢查。以項目中集成的 Lint 檢查為例,講述流程:
    4.3.3.1 配置 Gradle,引入 lint
    dependencies { ... compile 'com.android.tools.lint:lint-api:24.5.0' compile 'com.android.tools.lint:lint-checks:24.5.0' } 
    • lint-api: 官方給出的API,API并不是最終版,官方提醒隨時有可能會更改API接口。
    • lint-checks:已有的檢查。
    4.3.3.2 定義 IssueRegistry
    新建一個 MyIssueRegistry 類,繼承自 IssueRegistry。用來注冊我們自定義的全部 issue
    public class MyIssueRegistry extends IssueRegistry { @Override public List<Issue> getIssues() { System.out.println("********YXLint rules works!!!********"); return Arrays.asList( LogUsageDetector.ISSUE, ToastUsageDetector.ISSUE, ActivitySuperClassDetector.ACTIVITY_SUPER_CLASS_ISSUE, ... BuildGradleVersionDetector.ISSUE); } } 
    其中:
    • LogUsageDetector.ISSUE:用于檢查不允許直接使用 Log.* 方式輸出本地日志的代碼
    • ToastUsageDetector.ISSUE:用于檢查直接用 Toast 方式顯示 toast 的代碼
    • ActivitySuperClassDetector.ACTIVITY_SUPER_CLASS_ISSUE:用于檢查 Activity 的基類
    • BuildGradleVersionDetector.ISSUE:用于檢查 gradle 文件中不允許直接寫數字版本號的代碼
    4.3.3.3 gradle 清單項中注冊前面定義的 IssueRegistry
    jar { manifest { attributes('Lint-Registry': 'com.netease.htlint.lintrules.MyIssueRegistry') } } 
    4.3.3.4 定義 Detector
    MyIssueRegistry 類中聲明注冊了各個 DetectorIssue。IssueDetector 發現并報告,是 Android 程序代碼可能存在的風險。而這里就需要真正實現這些 Detector,以檢查 Activity 的基類為例。
     
    image
    ACTIVITY_SUPER_CLASS_ISSUE 這個 Issue 的定義需要使用 Issue.create(...) 方式實現,同時需要傳入 6 個參數分別如下:
    • A:一個固定的唯一的 id 代表這個 Issue
    • B:對于問題的簡短總結,描述問題而不是修復措施
    • C:完整的問題解釋和修復建議
    • D:問題類別,現在已有的問題類別有如下
      • Lint
      • Correctness (incl. Messages)
      • Security
      • Performance
      • Usability (incl. Icons, Typography)
      • Accessibility
      • Internationalization
      • Bi-directional text
    • E:優先級,必須在1到10之間,10為最重要/最嚴重。
    • F:嚴重級別,可選值有 Fatal, Error, Warning, Informational, Ignore
    • G:為 IssueDetector 提供映射關系,Detector 就是當前類。聲明掃描檢測的范圍 Scope,描述 Detector 需要分析時需要考慮的文件集,包括:Resource 文件或目錄、Java 文件、Class 文件
    ActivitySuperClassDetector 繼承自 Detector,并實現 Detector.JavaScaner。這里主要自定義實現的方法如上圖 H,I
    • H:檢查類的基類是 "android.support.v4.app.Activity" 或 "android.app.Activity"
    • I:具體檢查類的方法,這里需要排除非 yanxuan 包名下的代碼,判斷當前類的基類是否是 BaseBlankActivityBaseActionBarActivity?如果都不是的話,則報告錯誤
    • J:報出問題的方法:該方法中指定參數有:
      • 需要報錯的 Issue
      • 發生問題的代碼在語法樹上的節點
      • 發生問題的代碼位置
      • 警告的信息
    4.3.3.5 生成 jar 包
    完成上述步驟,可以在控制臺中通過命令 ../../gradlew assemble 來執行編譯任務,就可以輸出我們需要的 jar 文件 (htlintrules_jar-0.0.1.jar) 了
    4.3.3.6 jar 的使用
    按照 Google 方法,可以將 htlintrules_jar-0.0.1.jar 拷貝到 ~/.android/lint 中,但缺點是針對會影響一臺機器其他的工程。很明顯,我們的自定義 Lint 檢查有很多是項目中特有的一些編碼規范。
    為此,我們采用 LinkedIn 方案:將 jar 放到一個 aar 中。這樣我們就可以針對工程進行自定義 Lint,lint.jar 只對當前工程有效。
    在現有的 htlintrules_jar 工程的 build.gradle 中添加代碼,整體看起來如下:
    apply plugin: 'java' apply plugin: 'maven' dependencies { compile 'com.android.tools.lint:lint-api:24.5.0' compile 'com.android.tools.lint:lint-checks:24.5.0' } jar { manifest { attributes('Lint-Registry': 'com.netease.htlint.lintrules.MyIssueRegistry') } } configurations { lintJarOutput } dependencies { lintJarOutput files(jar) } defaultTasks 'assemble' 
    同時新建另一個工程 htlint,在其 build.gradle 文件中添加如下代碼:
    /* * rules for including "lint.jar" in aar */ configurations { lintJarImport } dependencies { lintJarImport project(path: ':htlintrules_jar', configuration: "lintJarOutput") } task copyLintJar(type: Copy) { from (configurations.lintJarImport) { rename { String fileName -> 'lint.jar' } } into 'build/intermediates/lint/' } project.afterEvaluate { def compileLintTask = project.tasks.find { it.name == 'compileLint' } compileLintTask.dependsOn(copyLintJar) } 
    最后在 app 工程的 build.gradle 中添加 htlint 引用,配置完成
    dependencies { compile project(':htlint') // lint 檢查庫 ... } 
    4.3.3.7 自定義 Lint 檢查執行及結果檢查
    ${項目工程}/app/ 目錄下執行 ../gradlew lint
     
    image
    根據提示查看 lint-result.html 文件,可以查看到前面編寫的 ActivitySuperClassDetector.ACTIVITY_SUPER_CLASS_ISSUE 已經生效,并且檢查出了相關的非規范代碼。
     
    image
     
    image
    4.3.3.8 排除錯誤的檢查結果
    前面很好的給出了檢查結果了,然而我們會發現,FullScreenVideoActivity 確實是需要的錯誤檢查結果,而 WXEntryActivity 卻不是,這個類是有集成微信分享時需要的,并且按照微信開放平臺的文檔來編寫,因此并不需要按照項目規范,繼承 BaseBlankActivityBaseActionBarActivity。為此,我們期望 WXEntryActivity 不應該被檢查出 WrongActivitySuperClass 錯誤
    為此,我們可以在 WXEntryActivity 類名簽名添加 SuppressLint 注解:
    @SuppressLint("WrongActivitySuperClass") public class WXEntryActivity extends Activity implements IWXAPIEventHandler{ ... } 
    1. 排除 java 類或者方法的 Lint 檢查
      若需要抑制某個 Issue 檢查,可以在類定義簽名或者方法定義簽名,添加注解 @SuppressLint(${IssueId})。這里設置的就是具體某個 Issueid
      若需要抑制全部的 Issue 檢查,可以使用 all 關鍵字,比如:@SuppressLint("all")
    2. 排除 xml 資源的 Lint 檢查
      如項目中引入微博分享 sdk,按照官方文檔,需要在 AndroidManifest 中聲明 com.sina.weibo.sdk.net.DownloadService 這個 Service,而這個 Service 會被 Lint 檢查為未定義,為此需要 xml 文件中也過濾部分代碼的 Lint 的檢查:
      <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.netease.yanxuan"> ... <service android:name="com.sina.weibo.sdk.net.DownloadService" android:exported="false" tools:ignore="MissingRegistered" /> </manifest> 
      這里對于單個 Issue 過濾的規則為:tools:ignore=${IssueId}
      如果需要過濾全部的 Issue,可以使用 all 關鍵字:tools:ignore="all"

    4.4 其他代碼檢查工具

    4.4.1 360 火線

    360 火線 是 360 公司和信息安全部門深度合作,定制的適用于 360 公司產品的安卓 APP 安全檢查規則??偣哺采w 61 項代碼檢查。使用也非常方便,細節看 使用文檔,可以直接使用 jar 包并執行命令或集成 Android Studio Plugin 執行檢查
     
    image

    4.4.2 pmd

    pmd 代碼檢查工具,包含 16 個規則集,涵蓋了 Java 的各種常見問題。其中規則集包含 基本(rulesets/basic.xml),終結函數(finalizer),未使用的代碼(rulesets/unusedcode.xml),設計(rulesets/design.xml) 等。
    相比 FindBugs,pmd 的一些規則更具爭議,但 pmd 支持我們構建自己的規則集
    <?xml version="1.0"?> <ruleset name="customruleset"> <description> Sample ruleset for developerWorks article </description> <rule ref="rulesets/design.xml"/> <rule ref="rulesets/naming.xml"/> <rule ref="rulesets/basic.xml"/> </ruleset> 

    4.5 代碼檢查工具整合及集成 jenkins

    為整合這些檢查工具,在 gradle 中自定義 check 命名,并依賴其他的 task。在執行檢查的時候,可以通過 ./gradlew check 來執行全部的檢查命令。
    check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint' 
    另一方面,這種代碼檢查,如果等到開發完成的時候再去執行,很可能問題積累了很多,甚至導致產品上線前,開發并不能來得及修正全部的問題。為此,可以將代碼檢查的命令集成 jenkins,保證開發每天都能看到當前的代碼的缺陷,能及時的修改

    5 總結

    我們從編碼前的編碼規范,編碼進行中的編碼模板,編碼結束后的代碼靜態檢查,保障了程序小伙伴們的代碼。除此之外,還有很多不完善的地方需要我們做進一步處理:
    1. 和特定項目相關的自定義 Lint 檢查項,僅支持了一部分的編碼規范,自定義 Lint 檢查項需要后續完成
    2. 雖然檢查工具很多,檢查的結果內容也很多,而很明顯,這些檢查工具相互之間是有重復的情況(主要是純 java 代碼部分的檢查),因此如果整理檢查結果,并過濾出我們真正關心的問題,也是后續需要完成的內容


    原文轉自:https://www.jianshu.com/p/6a38e9dcc0d9

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>