(八)下篇 Android 性能優(yōu)化 Lint 自定義Lint

小酌雞湯

業(yè)精于勤而荒于嬉轴捎,行成于思而毀于隨憋他。

本文來源《Android 性能優(yōu)化 全家桶》

為什么要自定義 Lint 进陡?

?在某些特殊情況下释牺,系統(tǒng)定義的 Lint 并不能滿足我們的需求萝衩,這時需要我們自己定義規(guī)則,然后利用 Android 的 Lint 工具幫助我們自動發(fā)現(xiàn)某些問題没咙。

自定義 Lint 的原理

?主要使用LinkedIn發(fā)方案:將jar放到一個aar中猩谊。然后 Android 項目依賴這個 aar 完成自定義 lint 檢查(只對當(dāng)前項目有效)。

現(xiàn)在祭刚,就一起實操體驗 自定義 Lint ~

(1)lint實操環(huán)境(可選項牌捷,用自己的環(huán)境和代碼也一樣)
  • SamplePop環(huán)境如下:
    ?Android Studio 4.0
    ?Gradle version 6.1.1
    ?Android API version 30
(2)創(chuàng)建Java工程,配置Gradle
apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.tools.lint:lint-api:26.0.0'
    implementation 'com.android.tools.lint:lint-checks:26.0.0'
}
  • lint-api: 官方給出的API(每個版本都會大變涡驮,對比了24暗甥,25,26捉捅,27這四個版本撤防,變化太大了)
  • lint-checks:已有的檢查。
我在實操時遇到的問題:
  • 我在配置Gradle文件時棒口,想著用最新的版本吧寄月,我就添加的是27的版本號。在編譯出的jar包放到~/.android/lint/后无牵,執(zhí)行l(wèi)int檢查剥懒,自己寫的Detector掃描器怎么都不生效,系統(tǒng)提示找不到對應(yīng)的SourceCodeScanner類(這個要看你的Detector是實現(xiàn)的哪個lint-api)合敦。
  • 我猜那可能是與系統(tǒng)自帶的掃描器版本不對應(yīng)啊,于是就查了下系統(tǒng)的自帶lint版本(系統(tǒng)自帶版本是26.0.0验游,我的gradle配置為27.0.0)充岛。修改gradle版本保檐,再次檢查,成功崔梗!
Lint系統(tǒng)的版本號查看
(3)創(chuàng)建Detector

?Detector負(fù)責(zé)掃描代碼夜只,發(fā)現(xiàn)問題并報告。
?下面掃描器的功能很簡單蒜魄,就是監(jiān)聽系統(tǒng)logandroid.util.Log的使用扔亥,lint檢查結(jié)果提示推薦使用 LogUtil 封裝類。

public class KJYRLogUtilDetector extends Detector implements Detector.UastScanner {
    public static final Issue ISSUE = Issue.create(
            "KJYRLogUtilCase",
            "科技猿人-避免使用Log",
            "使用LogUtil谈为,LogUtil對系統(tǒng)的Log類進行了邏輯封裝",
            Category.SECURITY, 5, Severity.WARNING,
            new Implementation(KJYRLogUtilDetector.class, Scope.JAVA_FILE_SCOPE));

    public List<String> getApplicableMethodNames() {
        return Arrays.asList("d", "e", "i", "v", "w");
    }

    @Override
    public void visitMethod(JavaContext context, UCallExpression node, PsiMethod method) {
        JavaEvaluator evaluator = context.getEvaluator();
        if (evaluator.isMemberInClass(method, "android.util.Log")) {
            String message = "kejiyuanren:請使用LogUtil封裝類";
            context.report(ISSUE, node, context.getLocation(node), message);
        }
    }
}

?細(xì)則說明:

  • getApplicableMethodNames:返回要監(jiān)聽的方法名稱集合
  • context.report(ISSUE, node, context.getLocation(node), message):檢查結(jié)果上報(report會自動處理被suppress(suppressLint)/ignore(tools:ignore)的警告)
  • Issue:由靜態(tài)工廠方法創(chuàng)建旅挤,由Detector 發(fā)現(xiàn)并報告。

?Issue字段說明:

  • id : 唯一值伞鲫,應(yīng)該能簡短描述當(dāng)前問題粘茄。利用Java注解或者XML屬性進行屏蔽時,使用的就是這個id秕脓。
  • summary : 簡短的總結(jié)柒瓣,通常5-6個字符,描述問題而不是修復(fù)措施吠架。
  • explanation : 完整的問題解釋和修復(fù)建議芙贫。
  • category : 問題類別。詳見下文詳述部分傍药。
  • priority : 優(yōu)先級磺平。1-10的數(shù)字,10為最重要/最嚴(yán)重怔檩。
  • severity : 嚴(yán)重級別:Fatal, Error, Warning, Informational, Ignore褪秀。
  • Implementation : 為Issue和Detector提供映射關(guān)系,Detector就是當(dāng)前Detector薛训。聲明掃描檢測的范圍Scope媒吗,Scope用來描述Detector需要分析時需要考慮的文件集,包括:Resource文件或目錄乙埃、Java文件闸英、Class文件。
(4)創(chuàng)建IssueRegistry

?提供需要被檢測的Issue列表

public class KJYRIssueRegistry extends IssueRegistry {
    @Override
    public List<Issue> getIssues() {
        return Arrays.asList(
                KJYRLogUtilDetector.ISSUE,
                KJYRSetTextDetector.SET_TEXT_I18N
//                HandlerDetector.ISSUE
        );
    }
}
(5)jar包生成

?我們將寫好的掃描器打包成jar

jar {
    manifest {
        attributes("Lint-Registry": "com.kejiyuanren.lint_jar.KJYRIssueRegistry")
    }
}
(6)jar包使用

?最終jar包是要提供給系統(tǒng)lint掃描的介袜,下面的兩個方案最明顯的區(qū)別就是影響范圍甫何。

(6.1)Google方案
//將jar拷貝到~/.android/lint中
$ mkdir ~/.android/lint/
$ cp lint_jar.jar ~/.android/lint/
Lint google方案拷貝到系統(tǒng)lint目錄

?缺點:針對所有工程,會影響同一臺機器其他工程的Lint檢查遇伞。即便觸發(fā)工程時拷貝過去辙喂,執(zhí)行完刪除,但其他進程或線程使用./gradlew lint仍可能會受到影響。

(6.2)LinkedIn方案

?LinkedIn 提供了另一種思路 : 將jar放到一個aar中巍耗。這樣我們就可以針對工程進行自定義Lint秋麸,lint.jar只對當(dāng)前工程有效。

Lint LinkedIn方案工程概覽

?lint_jar 工程:build.gradle

//注冊 KJYRIssueRegistry炬太,生成jar包
jar {
    manifest {
        attributes("Lint-Registry": "com.kejiyuanren.lint_jar.KJYRIssueRegistry")
    }
}

//聲明依賴
configurations {
    lintJarOutput
}

//依賴項實現(xiàn)
dependencies {
    lintJarOutput files(jar)
}

?lint_aar 工程:build.gradle

//配置lint的jar包
configurations {
    lintJarImport
}

//依賴項實現(xiàn)
dependencies {
    lintJarImport project(path: ":lint_jar", configuration: "lintJarOutput")
}

//將jar復(fù)制到lint目錄下的lint.jar
task copyLintJar(type: Copy) {
    from (configurations.lintJarImport) {
        rename {
            String fileName ->
                'lint.jar'
        }
    }
    into 'build/intermediates/lint/'
}

//將 copyLintJar 插入到 compileLint 之前執(zhí)行
project.afterEvaluate {
    def compileLintTask = project.tasks.find { it.name == 'compileLint' }
    compileLintTask.dependsOn(copyLintJar)
}

?lint 工程:build.gradle

dependencies {
    //添加lint aar
    implementation project(':lint_aar')
}
(7)lint檢查結(jié)果
Lint 自定義檢查結(jié)果-命令行檢查
Lint 自定義檢查結(jié)果-手動運行檢查
(8)實踐總結(jié)
  • lint的版本匹配問題灸蟆,如果遇到自定義lint不生效,請讓自己的lint版本與系統(tǒng)版本保持一致
  • 多看lint-checks中的現(xiàn)有Detector亲族,從源碼中學(xué)到更多炒考,更系統(tǒng)
  • 如果對自定義lint開發(fā)plugin感興趣,請參考文章結(jié)尾的: 美團 -> Android自定義Lint實踐
  • 如果對debug lint代碼感興趣霎迫,請參考文章結(jié)尾的:優(yōu)秀文章
Lint checks detector列表部分展示

小編的擴展鏈接

參考鏈接

新晴原野曠斋枢,極目無氛垢

?

舉手之勞,贊有余香女气!???比心??

?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末杏慰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子炼鞠,更是在濱河造成了極大的恐慌缘滥,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谒主,死亡現(xiàn)場離奇詭異朝扼,居然都是意外死亡,警方通過查閱死者的電腦和手機霎肯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門擎颖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人观游,你說我怎么就攤上這事搂捧。” “怎么了懂缕?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵允跑,是天一觀的道長。 經(jīng)常有香客問我搪柑,道長聋丝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任工碾,我火速辦了婚禮弱睦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渊额。我一直安慰自己况木,他們只是感情好垒拢,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著火惊,像睡著了一般子库。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上矗晃,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音宴倍,去河邊找鬼张症。 笑死,一個胖子當(dāng)著我的面吹牛鸵贬,可吹牛的內(nèi)容都是我干的俗他。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼阔逼,長吁一口氣:“原來是場噩夢啊……” “哼兆衅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嗜浮,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤羡亩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后危融,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體畏铆,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年吉殃,在試婚紗的時候發(fā)現(xiàn)自己被綠了辞居。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蛋勺,死狀恐怖瓦灶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抱完,我是刑警寧澤贼陶,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站乾蛤,受9級特大地震影響每界,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜家卖,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一眨层、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧上荡,春花似錦趴樱、人聲如沸馒闷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纳账。三九已至,卻和暖如春捺疼,著一層夾襖步出監(jiān)牢的瞬間疏虫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工啤呼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卧秘,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓翅敌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親惕蹄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354