主頁 > 移動端開發 > Kotlin Android專案靜態檢查工具的使用

Kotlin Android專案靜態檢查工具的使用

2020-09-14 11:13:23 移動端開發

Kotlin Android專案靜態檢查工具的使用

Kotlin Android專案可用的靜態檢查工具: Android官方的Lint, 第三方的ktlint和detekt.

靜態檢查工具

靜態檢查工具, 指不需要運行代碼, 對代碼進行檢查的工具.

不止代碼風格, 還可以檢查代碼的正確性, 是否有安全問題, 是否有性能問題等.

靜態檢查工具一般都具備可擴展性, 方便使用者制定和添加自己的規則.

比較流行的Java靜態檢查工具有CheckStyle, FindBugs, PMD等.

Android專案, 用Kotlin語言, 可用的靜態檢查工具: 官方的Android Lint, ktlint和detekt.

Android Lint

Android官方提供了代碼掃描工具, 叫lint.

在Android Studio運行lint, 在選單中選: Analyze -> Inspect Code..., 選擇范圍, 點OK即可運行.

也可以在命令列:

 ./gradlew lint

會分類報告出各種各樣的錯誤.

查看所有的Lint規則

點擊選單中的Analyze -> Inspect Code..., 在彈框的Inspection profile部分點擊表示更多的...按鈕, 會彈出框顯示當前的所有lint規則.

可以選擇是否包括規則, 編輯它們的優先級和應用范圍等.

Android Lint配置

全域的配置除了用IDE, 還可以通過lint.xml檔案.

還可以在gradle中配置, 比如:

android {
  ...
  lintOptions {
    // Turns off checks for the issue IDs you specify.
    disable 'TypographyFractions','TypographyQuotes'
    // Turns on checks for the issue IDs you specify. These checks are in
    // addition to the default lint checks.
    enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'
    // To enable checks for only a subset of issue IDs and ignore all others,
    // list the issue IDs with the 'check' property instead. This property overrides
    // any issue IDs you enable or disable using the properties above.
    check 'NewApi', 'InlinedApi'
    // If set to true, turns off analysis progress reporting by lint.
    quiet true
    // if set to true (default), stops the build if errors are found.
    abortOnError false
    // if true, only report errors.
    ignoreWarnings true
  }
}

特定代碼可以利用@SuprressLint注解. 比如: @SuppressLint("NewApi"), @SuppressLint("all").

特定xml檔案中可以用tools:ignore, 比如tools:ignore="UnusedResources", tools:ignore="NewApi,StringFormatInvalid", tools:ignore="all"等.

Android Lint現狀基準快照

可以在gradle中進行設定一個baseline:

android {
  lintOptions {
    baseline file("lint-baseline.xml")
  }
}

第一次添加這個, 運行lint之后, 會自動創建一個lint-baseline.xml檔案, 所有當前的問題都會被寫入這個檔案.

當再次運行lint, 就只會讀這個檔案, 作為基準, 只報告新的錯誤或警告. 并且提示其他原有問題在baseline檔案中, 被排除.

如果想重新生成baseline可以手動洗掉這個檔案, 重新進行.

ktlint

ktlint

代碼風格檢查, 遵循的是: Kotlin style guide

所有的規則代碼: github: ktlint rule set

ktlint安裝

app/build.gradle中添加:

configurations {
    ktlint
}

dependencies {
    ktlint "com.pinterest:ktlint:0.36.0"
    ...
}
task ktlint(type: JavaExec, group: "verification") {
    description = "Check Kotlin code style."
    classpath = configurations.ktlint
    main = "com.pinterest.ktlint.Main"
    args "src/**/*.kt"
    // to generate report in checkstyle format prepend following args:
    // "--reporter=plain", "--reporter=checkstyle,output=${buildDir}/ktlint.xml"
    // see https://github.com/pinterest/ktlint#usage for more
}
check.dependsOn ktlint

task ktlintFormat(type: JavaExec, group: "formatting") {
    description = "Fix Kotlin code style deviations."
    classpath = configurations.ktlint
    main = "com.pinterest.ktlint.Main"
    args "-F", "src/**/*.kt"
}

ktlint使用

檢查:

./gradlew ktlint

自動修改:

./gradlew ktlintFormat

并不是所有問題都可以自動修改, 有的問題需要手動改.

配置中的這句:

check.dependsOn ktlint

把運行檢查加到了check task中. 通過:

./gradlew check --dry-run

可以查看運行check task都會做哪些事情(dry run表示不用實際執行這些任務).

ktlint原始碼

看ktlint的原始碼, 程式的入口是Main.kt檔案中的main.

使用的規則集是:

class StandardRuleSetProvider : RuleSetProvider {

    // Note: some of these rules may be disabled by default. See the default .editorconfig.
    override fun get(): RuleSet = RuleSet(
        "standard",
        ChainWrappingRule(),
        CommentSpacingRule(),
        FilenameRule(),
        FinalNewlineRule(),
        ImportOrderingRule(),
        IndentationRule(),
        MaxLineLengthRule(),
        ModifierOrderRule(),
        NoBlankLineBeforeRbraceRule(),
        NoConsecutiveBlankLinesRule(),
        NoEmptyClassBodyRule(),
        NoLineBreakAfterElseRule(),
        NoLineBreakBeforeAssignmentRule(),
        NoMultipleSpacesRule(),
        NoSemicolonsRule(),
        NoTrailingSpacesRule(),
        NoUnitReturnRule(),
        NoUnusedImportsRule(),
        NoWildcardImportsRule(),
        ParameterListWrappingRule(),
        SpacingAroundColonRule(),
        SpacingAroundCommaRule(),
        SpacingAroundCurlyRule(),
        SpacingAroundDotRule(),
        SpacingAroundKeywordRule(),
        SpacingAroundOperatorsRule(),
        SpacingAroundParensRule(),
        SpacingAroundRangeOperatorRule(),
        StringTemplateRule()
    )
}

可以看到都是代碼格式相關的規則.

在線查看: ktlint ruleset standard

detekt

Github: detekt也是一個Kotlin的靜態分析工具.

官方網站: detekt.

detekt安裝

在專案根目錄的build.gradle檔案中添加:

plugins {
    id("io.gitlab.arturbosch.detekt").version("1.5.0")
}

allprojects {
    repositories {
        google()
        jcenter()
    }
    apply plugin: 'io.gitlab.arturbosch.detekt'
}

detekt {
    failFast = true // fail build on any finding
    buildUponDefaultConfig = true // preconfigure defaults
    config = files("$projectDir/config/detekt.yml")
    // point to your custom config defining rules to run, overwriting default behavior
    baseline = file("$projectDir/config/baseline.xml")
    // a way of suppressing issues before introducing detekt

    reports {
        html.enabled = true // observe findings in your browser with structure and code snippets
        xml.enabled = true // checkstyle like format mainly for integrations like Jenkins
        txt.enabled = true
        // similar to the console output, contains issue signature to manually edit baseline files
    }
}

運行./gradlew tasks可以看到相關任務被加進去了:

detekt
detektBaseline - Creates a detekt baseline on the given --baseline path.
detektGenerateConfig - Generate a detekt configuration file inside your project.
detektIdeaFormat - Uses an external idea installation to format your code.
detektIdeaInspect - Uses an external idea installation to inspect your code.

detekt使用

運行:

./gradlew detekt

進行檢測.

detekt {
}

塊是用來進行自定義的屬性設定的.

如果開啟了檔案輸出, 結果在: app/build/reports/detekt目錄下可以查看.

并且運行./gradlew check --dry-run可以發現, 運行check的時候也會執行detekt.

可以利用:

./gradlew detektGenerateConfig

生成組態檔: config/detekt/detekt.yml.

在組態檔中可以看到對各種規則的開關狀態, 編輯它可以進行定制.

detekt原始碼

程式的入口在detekt-climodule的Main.kt. 根據引數的不同回傳不同的Runner.

主要用于檢測的是這個Runner, 它的執行方法:

override fun execute() {
    createSettings().use { settings ->
        val (checkConfigTime) = measure { checkConfiguration(settings) }
        settings.debug { "Checking config took $checkConfigTime ms" }
        val (serviceLoadingTime, facade) = measure { DetektFacade.create(settings) }
        settings.debug { "Loading services took $serviceLoadingTime ms" }
        var (engineRunTime, result) = measure { facade.run() }
        settings.debug { "Running core engine took $engineRunTime ms" }
        checkBaselineCreation(result)
        result = transformResult(result)
        val (outputResultsTime) = measure { OutputFacade(arguments, result, settings).run() }
        settings.debug { "Writing results took $outputResultsTime ms" }
        if (!arguments.createBaseline) {
            checkBuildFailureThreshold(result, settings)
        }
    }
}

讀取配置, 創建服務, 執行檢測, 轉化輸出結果.

當沒有用戶自己宣告的組態檔時, 使用的默認組態檔是default-detekt-config.yml.

在這里可以看到對所有規則的默認開關狀態.

detekt的規則代碼放在detekt-rules這個module下: detekt rules.

官方檔案上也有說明, 比如這是performance分類下的rules: detekt performance.

包含ktlint的規則

detekt的規則種類更多, 并且它包含了ktlint的代碼檢查規則. 所有的ktlint規則被包裝在detekt-formatting這個module下, 見: detekt formatting rules.

但是并不是所有規則都默認開啟.

在組態檔的formatting塊可以查看具體的規則開關狀態.

如果需要修改定制, 需要生成自己的組態檔.

和Git hook結合

Lint工具的運行可以放在CI上, 也可以每次本地手動跑, 這樣在push之前就能發現錯誤并改正.

一種避免忘記的方法就是使用Git hook.

專案的.git/hooks檔案夾下自帶一些有意思的sample.

如何使用git hook

只要在.git/hooks路徑下添加對應名字的檔案, 如pre-push, pre-commit, 寫入想要的代碼即可.

hook檔案回傳0表示通過, 會進行下一步操作. 否則后面的操作會被放棄.

注意檔案要有執行權限: chmod +x 檔案名

如果不想跑hook可以加上 --no-verify 比如

git commit --no-verify

在提交之前運行靜態檢查

以ktlint為例, 我們希望每次commit的時候先運行./gradlew ktlint, 如果有issue則放棄提交.

.git/hooks中添加pre-commit檔案, 其中:

#!/bin/bash
echo "Running ktlint"

./gradlew ktlint
result=$?
if [ "$result" = 0 ] ; then    
   echo "ktlint found no problems"     
   exit 0
else
   echo "Problems found, files will not be committed."     
   exit 1
fi

detekt的添加也是類似, 官網上給了一個例子: detekt/git-pre-commit-hook.

如何track, 共享Git hooks

因為hooks檔案在.git目錄里, 只是在本地, 那么在團隊成員間如何共享呢?

根據這個問題: https://stackoverflow.com/questions/427207/can-git-hook-scripts-be-managed-along-with-the-repository

從git 2.9開始, 可以設定:core.hooksPath了.

可以在repo里面添加一個目錄hooks, 然后把git hooks檔案放進去track.

在命令列跑:

git config core.hooksPath hooks

把找hook檔案的目錄設定成指定目錄就好了.

總結

本文介紹了三種靜態檢查的工具:

  • Android Lint: Android自帶的Lint檢查. 檢查的內容比較豐富.
  • ktlint: Kotlin代碼樣式規范檢查. 特色: 有自動修正命令.
  • detekt: 除了code style還有performance, exceptions, bugs等方面的檢查. formatting模塊包含了ktlint的所有style檢查(雖然有的具體的規則默認不開啟, 但是可以配置), 是前者的超集.

這些工具都可以擴展, 添加自定義的檢查規則.

結合Git hook把靜態檢查在本地進行, 可以實作問題的盡早暴露和修改.

示例代碼

AndroidLintDemo

  • ktlint集成: ktlint分支.
  • detekt集成: detekt分支.

參考

  • Android Lint: 官方檔案
  • ktlint
  • detekt
  • Kotlin靜態代碼檢測方案分析

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/34294.html

標籤:Android

上一篇:android sdk manager 無法更新,解決連不上dl.google.com的問題

下一篇:Flutter開發之常用Widget

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more