Android效能優化之工具篇 — — Android Lint
Lint簡介
Android lint是在ADT16提供的新工具,它是一個程式碼掃描工具,能夠幫助我們識別資源、程式碼結構存在的問題。
Lint優化哪些問題
- 遺漏的翻譯(沒用上的翻譯)比如國際化未被翻譯的欄位值
- 佈局效能(以前是 layoutopt工具,可以解決無用佈局、巢狀太多、佈局太多)
- 未使用到資源
- 不一致的陣列大小
- 國際化問題(硬編碼)
- 圖示的問題(重複的圖示,錯誤的大小)
- 可用性問題(如不指定的文字欄位的輸入型)
- manifest檔案的錯誤
Lint 發現的每個問題都有描述資訊和等級,我們可以很方便地定位問題,同時按照嚴重程度進行解決。當然這個“嚴重程度”我們可以手動調節,有些原則問題不容侵犯,必須提升到 error,而有的個別問題也可以無視。
但是我們也不能過分依賴該工具,因為有些東西實際開發中會有自己的規則,有可能會出現衝突的地方。
Lint問題種類
Correctness 不夠完美的編碼,比如硬編碼、使用過時 API 等
Performanc 對效能有影響的編碼,比如:靜態引用,迴圈引用等
Internationalization 國際化,直接使用漢字,沒有使用資源引用等
Security 不安全的編碼,比如在 WebView 中允許使用 JavaScriptInterface 等
Usability 可用的,有更好的替換的 比如排版、圖示格式建議.png格式 等
Accessibility 輔助選項,比如ImageView的contentDescription往往建議在屬性中定義 等
Lint問題等級
| Fatal
| Error
| Warning
| Information
↓ Ignore
檢查問題列表詳見 點我跳轉
常見如下:
1. Correctness 1) DuplicatedIds Layout中id應該唯一 2) NewApi 程式碼中使用的某些API高於Manifest中的Min SDK 3) InconsistentArrays 字串國際化中,同一名字的的String-Array對應的item值不相同 4) Registered Activity/Service/ContentProvider沒有通過AndroidManifest註冊 5) Deprecated 使用已經廢棄的API 6) PxUsage 避免使用px,使用dp 2. Correctness:Messeges 1) MissingTranslation 字串國際化不完全 2) ExtraTranslation 國際化的字串,在預設位置(defaultlocale),沒有定義 3. Security 1) SetJavaScriptEnabled 不確定你的程式中確實需要JavaScript就不要執行SetJavaScriptEnabled。 2)ExportedContentProvider/ExportedReceiver/ExportedService/ExportedActivity ContentProvider/Receiver/Service/Activity的exported為true時,設定一個Permission,讓使用者獲取了Permission才能使用。 3) HardcodedDebugMode 不要在manifest中設定android:debuggable。 設定它,編譯的任何版本都要採用指定的debug模式。不設定,編譯Eng版本採用debug模式;編譯User版本採用release模式。 4. Performance 1) DrawAllocation 避免在繪製或者解析佈局(draw/layout)時分配物件。E.g.,Ondraw()中例項化Paint物件。 2) ObsoleteLayoutParam Layout中無用的引數。 3) UseCompoundDrawables 可優化的佈局:如包含一個Imageview和一個TextView的線性佈局,可被採用CompoundDrawable的TextView代替。 4) UseSparseArrays 儘量用Android的SparseArray代替Hashmap 5) DisableBaselineAlignment 如果LinearLayout被用於巢狀的layout空間計算,它的android:baselineAligned屬性應該設定成false,以加速layout計算。 6) FloatMath 使用FloatMath代替Math。 7) NestedWeights 避免巢狀weight,那將拖累執行效率 8) UnusedResources/UnusedIds 未被使用的資源會是程式變大,並且編譯速度降低。 9) Overdraw 如果為RootView指定一個背景Drawable,會先用Theme的背景繪製一遍,然後才用指定的背景,這就是所謂的“Overdraw”。 可以設定theme的background為null來避免。 10) UselessLeaf/UselessParent View或view的父親沒有用 5. Usability:Typography 1) TypographyDashes 特殊字元需用編碼代替:“–”需要用“–”;“—”需要用“—” 2) TypographyEllipsis 特殊字元需用編碼代替:“…”需要用“…” 3) TypographyOther 問題:“(c)”需要用“©” 6. Usability:Icons 1) IconNoDpi Icon在nodpi和指定dpi的目錄下都出現。 2) GifUsage Image不要用GIF,最好用PNG,可以用JPG。 7. Usability 1) BackButton Android中不要設計有Back的按鈕,Android中一般有Back的硬按鍵。 2) ButtonCase Button的“Ok”/“Cancel”顯示大小寫一定,不要全大寫或全小寫。有標準的資源的字串,不要自己再定義,而要用系統定義的:@android:string/ok和@android:string/cancel 8. Accessibility 1) ContentDescription ImageView和ImageButton應該提供contentDescription 9. Internationalization 1) HardcodeText 硬編碼的字串應該在資源裡定義 2) EnforceUTF8 所有XML資原始檔都應該以UTF-8編碼 ...
命令列執行:
命令列路徑
ADT:your ‘sdk’ dir\tools\lint.bat
AS:your ‘sdk’ dir\tools\bin\lint.bat
命令列使用
在’lint.bat’同級目錄開啟cmd
您可以通過’–help’獲取對應的幫助
Issue列表
lint –list list只是issue的id和summary的列表
lint –show show顯示詳細的issue資訊
disable/enable/check
lint –disable <list>
lint –enable <list>
lint –check <list>
Android-Lint所支援要檢測的Issue列表,預設有檢查(Severity為非Ignore)和忽略(Severity為Ignore)之分。
可以用disable不檢查指定<list>
中預設要檢查的id或category;用enable檢查指定<list>
中預設忽略的id或category;用check只檢查指定<list>
中的id或category。
1. disable/enable是在default列表的基礎上,disable/enable給定列表裡的;check是隻檢查列表裡的。
2. <list>
是issue id或category列表,用逗號隔開。
生成html/xml報表
lint –html <target_filename> <proj_dir>
生成html格式的報告
lint –html <target_filename> --url filepath=url
生成的html檔案中,還會引用別的檔案,可以通過url引數替換其中的地址,使其指向公共訪問的地方
lint –simplehtml <target_filename> <proj_dir>
生成格式簡單的html報告
lint –xml <target_filename> <proj_dir>
生成html格式的報告
自定義分析策略
lint –config <custom-lint_config_filename> <target_filename> <proj_dir>
雖然disable/enable/check選項可以改變本次檢查的問題行為,但是下次還要再次指定。可以通過config選項指定預設的全域性配置檔案。
注意:如果專案中已經有lint.xml檔案,對於某條issue的檢查來說,先用專案中lint.xml的規則,然後是config指定的規則,最後才是系統預設的規則。
IDE整合操作
Eclipse
開啟方式
- 右鍵專案 > Android Tools > Run Lint:xxx 如下圖:
- 導航欄 > Run Lint 如下圖(可選擇check範圍):
分析結果
設定
可以在這裡更改Lint檢查等級等…如下圖:
Android Studio
開啟方式
- 選擇要分析的專案或者檔案、資料夾,從選單欄,選擇Analyze > Inspect Code
- 選擇檢查範圍
顯示在Spectify Inspection Scope對話方塊的選項組合區取決於是否你選擇了一個專案,資料夾或者檔案。你可以通過選擇其它的單選按鈕來改變你想檢查的檔案。檢視Spectify Inspection Scope對話方塊中所有可選項的說明;
當你選擇一個專案,檔案或者目錄,Specity Sinpection Scope對話方塊顯示你選擇的專案,檔案或者目錄的路徑;
當你選擇超過一個專案,檔案,或者目錄,Specity Inspection Scope對話方塊顯示為你選中的檔案顯示一個選中的單選按鈕; - 展示檢查結果
在左邊的面板樹檢視中,通過展開和選擇錯誤型別,類別和問題來檢視檢查的結果;
右邊面板顯示了選中的錯誤型別,類別和檔案的檢查報告,提供了錯誤的名字和位置。在適當的地方,檢查報告展示瞭如問題摘要等其它資訊來幫助你修改問題;
在左邊面板樹檢視,右鍵單擊型別,類別和問題來顯示上下文選單;
基於上下文,你可以執行所有或者一些如下操作:跳轉到原始碼,排除和包含選中的選項,抑制問題,編輯設定,管理檢查警告,和重新執行檢查;
根據名稱檢查
以篩選無用的資源為例:
建立自定義範圍
從下拉列表中,記得選擇Project,有效的專案列表顯示在下面,按照圖示的樣式選擇過濾,這個結構符合我們平時的習慣;
Include 包含這個資料夾和它的檔案,但是不包含任何它的子資料夾
Include Recursively 包含這個資料夾和所有它的檔案,和子檔案和它們的檔案
Exclude 不包含這個資料夾和它的檔案,但是不包含任何它的子資料夾
Exclude Resursively 不包含這個資料夾和所有它的檔案,和子檔案和它們的檔案
如果你選擇資料夾,點選Exclude Recursively,這個資料夾以及所有子資料夾和檔案變為綠色;
如果你選擇資料夾下綠色的檔案,點選Exclude,檔案不在為綠色,但是檔案下的其它所有檔案還是綠色的;
設定
如下圖:
高階擴充套件
自定義lint
lint簡介
Lint.xml中關鍵是對issue(用id指定)的severity進行指定,lint.xml檔案由一個封閉的父標籤組成,它包含了一個或者多個子標籤。Lint為每一個定義了唯一的id屬性值,通過設定標識的安全屬性,你可以改變一個問題的安全級別,或者這個問題的lint檢查,並且可以指定該issue作用於指定的檔案還是當前專案。把lint.xml放在專案的根目錄中,命令列執行lint時候,lint就會用lint.xml中的規則。另外,執行lint時還可以用引數–config指定一個全域性的配置用於所有的專案。當專案中已有lint.xml,則對於某個issue而言,在lint.xml中沒有對該issue特別定製的情況下,–config指定的檔案中的該issue的定製才起作用。
e.g
<?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>
禁用lint檢查
在java中禁用檢查
在需要禁用的地方新增新增”@SuppressLint”註解,抑制在Java檔案中的所有lint問題檢查,使用all關鍵字。
e.g
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//下面的例子展示瞭如何在FeedProvider類中關閉ParserError問題檢查;
@SuppressLint("ParserError")
public class FeedProvider extends ContentProvider {...
在xml中配置lint檢查
可以使用tools:ignore屬性來禁止Lint對你的XML檔案指定部分進行檢查。在lint.xml檔案中加入下面的名稱空間,Lint工具才能識別這些屬性。
xmlns:tools="http://schemas.android.com/tools"
e.g
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="UnusedResources" >
<TextView
android:text="@string/auto_update_prompt" />
</LinearLayout>
為了禁止多個問題,使用逗號分隔的字串列出要禁止的問題。
tools:ignore=”NewApi,StringFormatInvalid”
為了在XML元素中抑制所有的lint問題檢查,使用all關鍵字。
tools:ignore=”all”
在Gradle中配置lint選項
Gradle的Android外掛允許你在你模組級別的build.gradle檔案中,使用lintOption{}塊配置一些lint選項,例如執行或者忽略什麼檢查。下面的程式碼片段向你展示了你可以配置的一些屬性。
e.g
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
}
}
...
推薦定製的路線:
在Eclipse中基於現有的問題,逐個分析並解決,然後我們就能得到一個Eclipse自動生成的lint.xml這個定製檔案;
然後這個lint.xml用於Eclipse和/或命令列下進行後續的檢查;
後續發現的問題再進一步處理,逐步完善lint.xml這個定製檔案。
特別地,一旦專案組決定採用Android-Lint,定製Lint規則要有對專案和團隊負責的專人來定製執行。Lint的目的是儘量多的暴露問題,解決問題,而個人會有刻意隱藏/規避錯誤的傾向。所以,驗收的時候,用大家討論認可的Lint規則做統一的執行檢查。
jenkins外掛
https://wiki.jenkins-ci.org/display/JENKINS/Android+Lint+Plugin
Android Lint Plugin可以解析lint生成的xml結果檔案,並生成趨勢圖、詳細條目、dashboard展示空間等
需要注意該外掛僅用於解析lint的xml report,在此之前你需要自行呼叫命令列生成結果檔案。