1. 程式人生 > >Android效能優化之工具篇 — — Android Lint

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

開啟方式

  1. 右鍵專案 > Android Tools > Run Lint:xxx 如下圖:
    aaa
  2. 導航欄 > Run Lint 如下圖(可選擇check範圍):
    這裡寫圖片描述

分析結果

這裡寫圖片描述

設定

可以在這裡更改Lint檢查等級等…如下圖:
這裡寫圖片描述

Android Studio

開啟方式

  1. 選擇要分析的專案或者檔案、資料夾,從選單欄,選擇Analyze > Inspect Code
    這裡寫圖片描述
  2. 選擇檢查範圍
    這裡寫圖片描述
    顯示在Spectify Inspection Scope對話方塊的選項組合區取決於是否你選擇了一個專案,資料夾或者檔案。你可以通過選擇其它的單選按鈕來改變你想檢查的檔案。檢視Spectify Inspection Scope對話方塊中所有可選項的說明;
    當你選擇一個專案,檔案或者目錄,Specity Sinpection Scope對話方塊顯示你選擇的專案,檔案或者目錄的路徑;
    當你選擇超過一個專案,檔案,或者目錄,Specity Inspection Scope對話方塊顯示為你選中的檔案顯示一個選中的單選按鈕;
  3. 展示檢查結果
    這裡寫圖片描述
    在左邊的面板樹檢視中,通過展開和選擇錯誤型別,類別和問題來檢視檢查的結果;
    右邊面板顯示了選中的錯誤型別,類別和檔案的檢查報告,提供了錯誤的名字和位置。在適當的地方,檢查報告展示瞭如問題摘要等其它資訊來幫助你修改問題;
    在左邊面板樹檢視,右鍵單擊型別,類別和問題來顯示上下文選單;
    基於上下文,你可以執行所有或者一些如下操作:跳轉到原始碼,排除和包含選中的選項,抑制問題,編輯設定,管理檢查警告,和重新執行檢查;

根據名稱檢查

以篩選無用的資源為例:
這裡寫圖片描述
這裡寫圖片描述

建立自定義範圍

這裡寫圖片描述
這裡寫圖片描述
從下拉列表中,記得選擇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,在此之前你需要自行呼叫命令列生成結果檔案。
效果圖