- 打造流暢的Android App
- 蕭文翰
- 3852字
- 2022-07-29 14:49:14
2.2 使用Android Lint進(jìn)行代碼審查
Android Lint已經(jīng)默認(rèn)集成在IDE中,通過(guò)運(yùn)行Lint來(lái)檢查代碼,從而發(fā)現(xiàn)隱藏在代碼中疑似的質(zhì)量問(wèn)題,隨后再通過(guò)人工復(fù)查更正這些問(wèn)題。
運(yùn)行Lint無(wú)須執(zhí)行App,也無(wú)須編寫額外的測(cè)試用例。它可以自動(dòng)生成報(bào)告,還可以通過(guò)自定義的方式降低或提高檢測(cè)問(wèn)題的嚴(yán)重級(jí)別或添加忽略檢查項(xiàng)。默認(rèn)配置下,當(dāng)我們執(zhí)行編譯操作時(shí),Android Studio會(huì)自動(dòng)運(yùn)行Lint檢查。當(dāng)然,我們也可以在需要時(shí)手動(dòng)運(yùn)行檢查。
2.2.1 Android Lint概述及基本概念
Android Lint可以檢查出Android App代碼中的隱含問(wèn)題,這些問(wèn)題主要分為6類:正確性(Correctness)、安全性(Security)、性能(Performance)、易用性(Usability)、無(wú)障礙性(Accessbility)以及國(guó)際化(l18n)。默認(rèn)情況下,當(dāng)使用Android Studio進(jìn)行編譯時(shí),會(huì)自動(dòng)運(yùn)行Lint檢查。圖2.10展示了Lint的工作原理。

圖2.10 Lint的工作原理
App源代碼指整個(gè)工程的源代碼文件,除了Java、Kotlin、XML外,還包括應(yīng)用圖標(biāo)素材文件以及用于代碼混淆的ProGuard配置文件。lint.xml文件是Lint檢查的配置文件,當(dāng)我們需要自定義檢查規(guī)則時(shí),通常會(huì)編輯這個(gè)文件。Lint工具是一個(gè)靜態(tài)代碼審查工具,可以從命令行或Android Studio中啟動(dòng)它,這一步通常會(huì)在發(fā)布產(chǎn)品前進(jìn)行。Lint分析結(jié)果分類是Lint工具的檢查結(jié)果,它覆蓋了圖2.10中展示的6類問(wèn)題。
2.2.2 運(yùn)行Lint檢查
我們可以在任何時(shí)刻、不同環(huán)境下運(yùn)行Lint檢查。
啟動(dòng)Android Studio,按照默認(rèn)工程配置新建一個(gè)名為My Application的工程,然后打開Android Studio中的終端(Terminal),輸入gradlew lint,按回車鍵,即可開始運(yùn)行。首次運(yùn)行會(huì)耗費(fèi)一些時(shí)間下載JAR包,結(jié)束后會(huì)以HTML和XML形式給出檢查結(jié)果,如圖2.11所示。

圖2.11 從命令行運(yùn)行Lint
用瀏覽器打開HTML格式的報(bào)告,可看到所有疑似問(wèn)題,如圖2.12所示。

圖2.12 Lint報(bào)告示例
此外,對(duì)于不同的編譯版本,還可以進(jìn)行特定的檢查。在My Application工程中,打開appModule的build.gradle文件。可以看到,在默認(rèn)情況下,只有一個(gè)release版本的編譯配置,如圖2.13所示。

圖2.13 Lint報(bào)告示例
實(shí)際上,還有一個(gè)Debug版本類型,這個(gè)類型是Android Studio自動(dòng)配置的。如果我們想重新定義Debug版本的編譯配置,就可以在buildTypes節(jié)點(diǎn)下顯式定義Debug版本類型。當(dāng)我們需要僅檢查Debug版本時(shí),可執(zhí)行g(shù)radlew lintDebug,其他版本同理。
隨著程序邏輯日益復(fù)雜,代碼量日益增多,我們還有可能需要只審查部分代碼,或者采用不同的配置文件。這種情況下,使用集成在Android Studio中的Lint工具更加方便。
依次單擊菜單欄中的分析(Analyze),在彈出的菜單中選擇代碼檢查(Inspect Code...),在彈出的窗口中可以選取代碼檢查范圍和配置文件,如圖2.14所示。

圖2.14 在Android Studio中運(yùn)行Lint檢查
默認(rèn)情況下,檢查的項(xiàng)目和在命令行啟動(dòng)檢查的項(xiàng)目大體一致。不同的是,在Android Studio中,執(zhí)行代碼檢查的結(jié)果需在Inspect Results視圖中查看,如圖2.15所示。

圖2.15 在Android Studio中查看Lint檢查結(jié)果
由圖2.15可見,其結(jié)果和命令行方式檢查的結(jié)果是一致的,并且更加直觀。在修改代碼時(shí)也會(huì)更加方便,如圖2.16所示。

圖2.16 在Inspect Results視圖中快速修改代碼
由此可見,可視化的Lint檢查更為簡(jiǎn)便。
2.2.3 自定義Lint檢查范圍
接下來(lái),我們來(lái)探討如何自定義Lint的檢查范圍。在Android Studio中,已經(jīng)預(yù)設(shè)了多個(gè)檢查范圍供我們選擇,為方便擴(kuò)展和自定義檢查需求,還開放了自定義Lint檢查范圍,主要通過(guò)廣泛使用的Scope窗口實(shí)現(xiàn)。下面讓我們逐一了解它們吧。
1.使用預(yù)置的檢查范圍
回顧圖2.14,在Inspection scope部分有4個(gè)單選框可供選擇:Whole project表示整個(gè)工程;Module 'App'表示只檢查App模塊;Directory'...\app[app]'和當(dāng)前被打開的文件有關(guān),表示只檢查當(dāng)前被打開的文件;而Custom scope表示自定義范圍,我們重點(diǎn)關(guān)注它。
選中Custom scope,展開旁邊的下拉菜單,可以看到預(yù)置的檢查范圍,如圖2.17所示。

圖2.17 預(yù)置的檢查范圍
從圖2.17中可以看到,有多個(gè)菜單項(xiàng)可供選擇,我們先了解一下它們都代表什么含義。
· Project Files:當(dāng)前工程的所有文件。
· Project Source Files:當(dāng)前工程的所有源代碼文件。
· Project Production Files:當(dāng)前工程中的所有生產(chǎn)文件。
· Project Test Files:當(dāng)前工程中的所有測(cè)試文件。
· Scratches and Consoles:提供了兩種臨時(shí)的文件編輯環(huán)境,通常用來(lái)存放文本或代碼片,該選項(xiàng)在實(shí)際開發(fā)中很少用到。
· Module 'app':僅app模塊的文件。
· Class Hierarchy:當(dāng)我們選取這個(gè)菜單項(xiàng)并單擊OK按鈕時(shí),會(huì)彈出新的窗口,窗口里顯示當(dāng)前工程中的所有類。我們可以使用窗口里的搜索功能過(guò)濾要檢查的類。在未過(guò)濾的情形下,Lint會(huì)檢查所有類。以Activity作為過(guò)濾文本篩選出類,由于新建的工程僅包含一個(gè)Activity類,因此篩選結(jié)果如圖2.18所示。

圖2.18 篩選結(jié)果示例
2.創(chuàng)建自定義檢查范圍
當(dāng)預(yù)設(shè)的檢查范圍無(wú)法滿足我們的自定義需求時(shí),可以進(jìn)一步對(duì)代碼檢查范圍進(jìn)行自定義。
單擊圖2.17中下拉菜單右側(cè)的三個(gè)點(diǎn)按鈕,彈出Scope窗口(見圖2.19),我們?cè)谶@里配置自定義檢查范圍。

圖2.19 Scope窗口
注意:這里的Scope配置也可用于其他功能,比如搜索。
默認(rèn)情況下,Scope配置為空。單擊界面左上角的“+”,然后選擇Local來(lái)添加新范圍。
Local和Share的共同點(diǎn)是給定代碼檢查范圍,區(qū)別是Share還可用于具有范圍字段的其他項(xiàng)目。也就是說(shuō),Local類型的Scope配置是個(gè)人使用的,保存在個(gè)人的workspace中,默認(rèn)保存在/config/projects/<project_name>/.idea/workspace.xml中;Share類型的Scope配置是整個(gè)工程的,可以通過(guò)版本控制系統(tǒng)被團(tuán)隊(duì)成員共享,它的默認(rèn)路徑在/config/projects/<project_name>/.idea/scopes/中。
此處我們以Local類型的Scope為例進(jìn)行介紹,名稱為UIView,即僅檢查和UI視圖相關(guān)的類。
仔細(xì)觀察圖2.20中的內(nèi)容,Pattern的含義是正則表達(dá)式,如果讀者對(duì)正則表達(dá)式比較熟悉,那么完全可以直接填寫合法的正則表達(dá)式,達(dá)到定義范圍的目的。

圖2.20 名稱為UIView的Scope配置
或者使用窗口右側(cè)的4個(gè)按鈕來(lái)控制檢查范圍,分別說(shuō)明如下:
· Include:包含此文件夾及其文件,不包含子文件夾中的內(nèi)容。
· Include Recursively:包含此文件夾及其文件,遞歸包含所有子文件夾及其文件。
· Exclude:排除此文件夾及其文件,不遞歸排除所有子文件夾及其文件。
· Exclude Recursively:排除此文件夾及其所有文件,遞歸排除所有子文件夾及其文件。
通過(guò)對(duì)照可輕松地發(fā)現(xiàn),圖2.20中,我們選擇了MainActivity.java和activity_main.xml兩個(gè)文件。最后,單擊OK按鈕確認(rèn)。
2.2.4 自定義Lint檢查類型
2.2.3小節(jié)中,我們主要針對(duì)Lint的檢查范圍做了詳細(xì)的說(shuō)明,本小節(jié)主要介紹Lint的檢查類型。這里介紹3種自定義Lint檢查類型的方法,分別對(duì)應(yīng)不同的需求。讀者可根據(jù)實(shí)際項(xiàng)目的需要結(jié)合使用。
1.使用和自定義Lint配置文件
在Android Lint中內(nèi)置了多種靜態(tài)代碼檢查的配置文件。我們可以直接使用它們,也可以更改它們的名稱、說(shuō)明、范圍甚至是嚴(yán)重級(jí)別,也可以隨時(shí)啟用或禁用某個(gè)配置文件,達(dá)到跳過(guò)某種檢查的目的。
我們先來(lái)看默認(rèn)情況下會(huì)進(jìn)行哪些類型的檢查。
打開圖2.14所示的窗口,選擇Inspection Profile部分中的三個(gè)點(diǎn)按鈕,出現(xiàn)Inspections窗口,如圖2.21所示。

圖2.21 Inspections窗口
檢查的項(xiàng)目、說(shuō)明以及啟用狀態(tài)等信息一目了然地羅列在這個(gè)窗口中。我們除了可以通過(guò)復(fù)選框啟用/禁用某個(gè)檢查外,還需關(guān)注一個(gè)地方,就是位于左上角的Profile下拉菜單。
展開Profile下拉菜單,默認(rèn)情況下,預(yù)置了Default和Project Default兩個(gè)配置。顯而易見,前者是對(duì)整個(gè)Android Studio而言的,將影響所有的工程;后者是對(duì)單個(gè)工程而言的。在未做任何自定義配置的前提下,這二者是相同的。
同時(shí),我們還可以單擊下拉菜單右側(cè)的小齒輪,添加更多自定義的菜單項(xiàng)。由Default復(fù)制而來(lái)的配置依舊影響所有工程,由Project Default復(fù)制而來(lái)的配置則僅對(duì)當(dāng)前工程有效。當(dāng)然,我們還可以對(duì)其進(jìn)行重命名、刪除、導(dǎo)入以及導(dǎo)出等操作。
2.配置lint.xml文件
通過(guò)前面的學(xué)習(xí),我們已經(jīng)可以實(shí)現(xiàn)特定范圍、特定檢查種類的自定義了??瓷先ニ坪跻呀?jīng)滿足了靜態(tài)代碼檢查的需要,事實(shí)上也確實(shí)如此。那為什么這里還要介紹lint.xml文件呢?
想象這樣一種情況,假設(shè)我們的工程有多個(gè)XML布局文件,要求某個(gè)或某幾個(gè)布局文件需要單獨(dú)定義檢查類型。根據(jù)現(xiàn)有的知識(shí),我們需要定義不止一個(gè)Scope,然后定義不止一個(gè)Profile,最后挨個(gè)啟動(dòng)檢查。是不是很煩瑣?有沒(méi)有辦法簡(jiǎn)化呢?答案是肯定的——借助lint.xml定義規(guī)則,即可完成快捷方便的檢查。
lint.xml位于整個(gè)工程根目錄下,默認(rèn)不會(huì)自動(dòng)創(chuàng)建,需要我們手動(dòng)添加這個(gè)文件,格式遵循標(biāo)準(zhǔn)的XML,一個(gè)規(guī)則定義的范例如下:

可見,lint.xml文件由封閉的<lint>標(biāo)記包裹,其中包含多個(gè)<issue>子元素,每個(gè)<issue>子元素定義了唯一id。
想要理解如何定義issue子元素并不難,如以上代碼片段所示,其中包含4個(gè)issue子元素,分別是忽略了所有IconMissingDensityFolder類型的檢查,對(duì)不同XML文件進(jìn)行不同問(wèn)題類型的忽略,不包含任何自組件的View,以及設(shè)置了HardcodedText問(wèn)題類型級(jí)別為error。當(dāng)Lint檢查被執(zhí)行時(shí),以上配置將生效。完整的問(wèn)題id列表以及對(duì)應(yīng)的描述可以通過(guò)執(zhí)行l(wèi)int –list查看,該文件位于[Android Sdk目錄](méi)\tools\bin\。
3.在源代碼文件中添加忽略項(xiàng)
除了上述在lint.xml中定義檢查規(guī)則外,我們還可以直接在源代碼文件中添加指定的忽略規(guī)則,支持Java、Kotlin和XML三種類型的源代碼。接下來(lái),我們對(duì)上述3類代碼分別進(jìn)行講解。
(1)Java/Kotlin
首先來(lái)看Java/Kotlin,當(dāng)我們需要對(duì)類中某個(gè)方法進(jìn)行忽略規(guī)則的定義時(shí),在方法聲明前添加注解即可,參考下面的代碼片段:
Java語(yǔ)言:

Kotlin語(yǔ)言:

當(dāng)我們需要對(duì)整個(gè)類進(jìn)行忽略規(guī)則的定義時(shí),在類聲明前添加注解即可,參考如下代碼片段:
Java語(yǔ)言:

Kotlin語(yǔ)言:

特別地,當(dāng)我們需要排除整個(gè)類的所有類型的檢查時(shí),可按照如下方式添加注解:

(2)XML
在對(duì)XML文件添加排除項(xiàng)前,需要先添加如下定義命名空間,以便Lint工具識(shí)別添加的屬性:

當(dāng)我們需要添加排除項(xiàng)時(shí),只需在對(duì)應(yīng)的布局節(jié)點(diǎn)處使用tools:ignore屬性即可,參考下面的代碼片段:

上述代碼中,我們?yōu)長(zhǎng)inearLayout添加了排除項(xiàng)UnusedResources和StringFormatInvalid。其中的子元素TextView會(huì)受其父元素的影響,也將排除相對(duì)應(yīng)類型的檢查。
和Java/Kotlin類似,要排除所有的檢查項(xiàng),使用all關(guān)鍵字即可。
4.在整個(gè)Module中添加忽略項(xiàng)
某些情況下,整個(gè)工程可能包含多于一個(gè)Module,統(tǒng)一的檢查規(guī)則可能不適用于所有Module。因此,我們需要一種方法對(duì)單個(gè)Module進(jìn)行規(guī)則定義,秘訣就在于每個(gè)Module的build.gradle文件。
要定義某個(gè)Module的檢查規(guī)則是很容易的,只需在android節(jié)點(diǎn)下添加lintOptions代碼塊即可。我們將下面的代碼片段加入之前新創(chuàng)建的My Application工程的app模塊對(duì)應(yīng)的build.gradle文件內(nèi):

由于build.gradle文件發(fā)生了更改,因此需要Sync才能使這些更改生效。
再次運(yùn)行Lint檢查,得到如圖2.22所示的結(jié)果。

圖2.22 添加忽略規(guī)則的檢查結(jié)果
與圖2.15對(duì)比發(fā)現(xiàn),有關(guān)舊版本庫(kù)的warning已經(jīng)消失不見了,這正是排除了GradleDependency規(guī)則的結(jié)果——不對(duì)仍然使用舊版本庫(kù)進(jìn)行警告。
- Vue.js 3.x快速入門
- Learning Scala Programming
- PostgreSQL Cookbook
- aelf區(qū)塊鏈應(yīng)用架構(gòu)指南
- Python 3破冰人工智能:從入門到實(shí)戰(zhàn)
- Mathematica Data Analysis
- Asynchronous Android Programming(Second Edition)
- Creating Mobile Apps with jQuery Mobile(Second Edition)
- Python深度學(xué)習(xí)原理、算法與案例
- Java零基礎(chǔ)實(shí)戰(zhàn)
- Processing創(chuàng)意編程指南
- C語(yǔ)言程序設(shè)計(jì)實(shí)訓(xùn)教程與水平考試指導(dǎo)
- Training Systems Using Python Statistical Modeling
- R語(yǔ)言數(shù)據(jù)挖掘:實(shí)用項(xiàng)目解析
- Mudbox 2013 Cookbook