先來段developer的官方引用:html
Android Studio provides a code scanning tool called Lint that can help you to easily identify and correct problems with the structural quality of your code, without having to execute the app or write any test cases.java
該圖詮釋了Lint工具是如何檢測應用源代碼的:android
做爲移動應用開發者,咱們總但願發佈的apk文件越小越好,不但願資源文件沒有用到的圖片資源也被打包進apk,不但願應用中使用了高於minSdk的api,也不但願AndroidManifest文件存在異常,lint就能解決咱們的這些問題。git
Android Lint是Google提供給Android開發者的靜態代碼檢查工具。使用Lint對Android工程代碼進行掃描和檢查,能夠發現代碼潛在的問題,提醒程序員及早修正。程序員
爲保證代碼質量,美團在開發流程中加入了代碼檢查,若是代碼檢測到問題,則沒法合併到正式分支中,這些檢查中就包括Lint。github
其餘博客就不一一列舉了。api
再來段官方文檔:數組
The Lint tool checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization. You can run Lint from the command-line or from Android Studio.app
簡要來講:maven
佈局性能(之前是 layoutopt工具,能夠解決無用佈局、嵌套太多、佈局太多)
未使用到資源
不一致的數組大小
國際化問題(硬編碼)
圖標的問題(重複的圖標,錯誤的大小)
可用性問題(如不指定的文本字段的輸入型)
manifest文件的錯誤
內存泄露 --- 如:handle的不當使用 。
佔內存的資源及時回收 --- 如:cursor未關閉等
Lint檢查的配置文件,該文件即爲你修改的某些Lint配置項,其須要在對應模塊的根目錄,Lint Tool會自動掃描模塊目錄下是否有對應的lint配置文件。
該lint文件以下所示:
其中severity是嚴重級別:error,ignore,warning。注意其也能夠只指定部分文件
@SuppressLint
註解,其容許在任何地方定義,如在方法體上定義,則忽略該方法體的Lint檢測。@SuppressLint("NewApi")
最爲常見,@SuppressLint("all")
意爲忽略全部規則。
在xml文件,首先引入:
namespace xmlns:tools="http://schemas.android.com/tools"
簡單介紹下tool,用於告知as,哪些屬性可被忽略,只在設計佈局時有效:
Lint提示。tools:ignore = "contentDescription"
意爲忽略lint的imageview的contentDescription屬性,該屬性用於視力障礙者。
預覽佈局。
tools:text
如某控件在Java代碼層動態設置text屬性,而你須要看預覽效果,一般會設置 android:text="I am a title"
,等預覽完畢再進行刪除,使用tools,則徹底達到預覽效果。
tools:context
預覽佈局時,ide可知採用哪一種主題,還可Go to Related files。
具體tools分析:android中xml tools屬性詳解
分析了那麼多,意在說明Lint工具的重要性,那麼下一階段則是如何在as中使用,以及配置,以及結合公司代碼進行項目檢查。
Analyze」菜單中選擇「Inspect Code」,其中能夠選擇scope,即檢測範圍,也能夠選擇不一樣的檢測配置,咱們先進行默認的配置檢測吧。檢測須要必定的時間,結果會在EventLog顯示:
能夠看到,咱們的項目有不少問題,好比我選擇了Correctness中的Using dp instead of sp for text sizes屬性,發現應用中有2處在textSize中誤用了dp,其給出了類的具體位置和解決方案。可能你以爲這些無關大雅,那麼能夠查看Probable bugs項,在其中找到一項 String comparison using '==',instead of 'equals()',能夠看到SecurityBankCardListActivity類中的有一行代碼:
this.mBankCard.getCardId() == mBankCard.getCardId()//cardId爲String類型
在此就不一一列舉。
可能你會以爲Lint分析的太過詳細,我沒法迅速找到問題,那麼你能夠點擊,其分爲四類,咱們應只關注前2類。
運行gradle lint
,而後在app/build/outputs打開lint-results.xml
打開設置對話框,找到Editor,而後是Inspections,選擇某一個Lint選項,修改嚴重等級,如圖:
gradle中的Android插件的lintOptions,具體lintOptions屬性,可參照官方文檔
咱們在實際使用Lint中遇到了如下問題:
原生Lint沒法知足咱們團隊特有的需求,例如:編碼規範。
原生Lint存在一些檢測缺陷或者缺乏一些咱們認爲有必要的檢測。
基於上面的考慮,咱們開始調研並開發自定義Lint。
那咱們的項目須要自定義Lint嗎,我以爲頗有必要,舉幾個例子:
咱們有MuLog模塊,可是仍然有開發同事會使用android自帶的Log工具類或java的System.out.print,顯然咱們應該能夠選擇強制開發同事調用MuLog,若是調用Log等,編譯器會報錯等提示。
加強HashMap檢測,Lint檢測中有一項是Java性能檢測,常見的就是:HashMap can be replaced with SparseArray。例以下面代碼,原生Lint只能檢測第一種狀況。
public static void testHashMap() { HashMap<Integer, String> map1 = new HashMap<Integer, String>(); map1.put(1, "name"); HashMap<Integer, String> map2 = new HashMap<>(); map2.put(1, "name"); Map<Integer, String> map3 = new HashMap<>(); map3.put(1, "name"); }
Intent攜參,activity頁面間的跳轉須要intent,而須要傳輸數據時,須要extra,對應的該extra都須要一個key,該key應該是跳轉類中的命名常量,而不是寫死在putExtra("key","value")
裏,咱們能夠強制開發同事Intent攜參的key必須爲按照EXTRA_<name>格式命名的常量。
好比Android因爲性能的緣由應該儘可能減小或避免使用枚舉。
好比線程的建立不該該是簡單的new Thread,而是應該使用同一的全局的線程池。
參看美團自定義Lint實踐文章,具體流程以下所示:
http://tools.android.com/tips...
根據該文章,將寫好的jar拷貝到android/lint文件夾下,再下一次運行IDE時,IDE會檢測其內的jar文件。
缺點:開發人員的機器上全部的Android工程都會受到影響,並且每一個開發人員間的拷貝成本大。
https://engineering.linkedin....
LinkedIn提供了另外一種思路 : 將jar放到一個aar中。這樣咱們就能夠針對工程進行自定義Lint,lint.jar只對當前工程有效。
aar文件中放入lint.jar是可選的。該lint.jar將會經過app的lint task被執行。
因此咱們選擇該方案。
aar雖然很方便,可是在團隊內部推廣起來,依然很困難。
配置繁瑣,不易推廣。每一個庫都須要自行配置lint.xml、lintOptions,而且compile aar。
不易統一。各庫之間須要使用相同的配置,保證代碼質量。但如今手動來回拷貝規則,且配置文件能夠本身修改。
因而咱們想到開發一個plugin,統一管理lint.xml和lintOptions,自動添加aar。
集成了原生lint和自定義lint的全部檢查規則
內置lintOptions(全部warning視爲error,只輸出htmlReport到${project.projectDir}/lint-report/lint-report.html)和 lint.xml。集成此插件後,原有配置會被覆蓋,沒有配置的也會執行插件中的配置
此處錯誤,僅僅是IDE提示開發人員須要進行修改,其仍然能夠提交該代碼並運行該代碼。
建立lint的java項目,包含的是自定義的lint規則
建立lint的library項目,僅用來輸出包含lint.jar的aar
建立Android項目,用來測試自定義lint規則
建立groovy項目,用於生產plugin
svn的pre-commit如何進行觸發lint檢查,以便開發人員每次提交代碼時,都會啓動lint檢查提交的代碼是否包含自定義Error,並拒絕其提交該代碼。
project中的build.gradle文件的buildscript的dependencies中添加:
classpath 'com.mucfc.muna.lint:plugin:latest.integration'
在module中,如muapp中添加:
apply plugin: 'MTLintPlugin'
上述代碼完成後,全部的開發人員當編寫相關的代碼時,如Log.d()都會出現錯誤提示,並且不會影響項目。
現階段,我已經上傳到公司maven庫的有:plugin和aar。因此若是項目引用該plugin,則針對業務須要能夠逐漸擴展該lint規則。
svn的提交前代碼檢查腳本。
美團技術:Android自定義Lint實踐
LinkedIn Engineering:Writing Custom Lint Checks with Gradle
Google關於lint.jar:AAR Format
Google blog:Writing a Lint Check
yongce-AndroidDevNotes:自定義Android Lint規則