對Android Studio支持的六類Android Lint規則, 本文主要對Performance包含的32個項的說明,主要內容都是文檔翻譯,適當加一些本身的感想。html
未被使用的資源id,在layout文件中定義了資源ID從未被使用過,但有時候它們可讓layout更容易閱讀,沒有必要刪除未使用的資源id。java
過分繪製:一個繪製區域被繪製的次數多於一次。android
若是給一個root view設置了背景圖,就要給它設置一個background=null
的theme
,不然繪製過程會先繪製theme
的background
,而後再繪製設置的背景圖,徹底覆蓋以前繪製的theme.background
,這是 過分繪製。算法
這個檢測器依賴於根據掃描Java代碼找出哪些佈局文件與哪些Activity相關聯,目前它使用的是一種不精確的模式匹配算法。所以,可能會因錯誤地推斷佈局與活動的關聯而給出錯誤的提醒。app
若是想把一個背景圖應用在多個頁面上,能夠考慮自定義theme
,並把背景圖設置在theme
裏,在layout
中設置theme
代替設置background
。若是背景圖中有透明的部分,而且但願他和theme
的背景有層疊效果,那麼能夠選擇先把兩個背景合併成一個背景圖以後,在定義到theme
裏。less
關於SVG的使用,給出一篇參考文章:Android vector標籤 PathData 畫圖超詳解,Android Studio能夠建立使用SVG繪製出的drawable圖像資源。ide
沒有包含任何View,也沒有設置背景的Layout是多餘的,能夠去掉。讓界面更趨於扁平,嵌套更高效。函數
若是一個包含
View
的Layout
沒有兄弟層級的Layout
,而他的外部ViewGroup
又不是ScrollView
或者root級別,那麼這個Layout
能夠移除,讓他包含的View
直接包含在它的父層級的Layout
中。讓界面更趨於扁平,嵌套更高效。oop
Layout
嵌套過深會影響性能,考慮使用平鋪類型的Layout代替。默認最深的View嵌套是10層,也能夠經過環境變量ANDROID_LINT_MAX_DEPTH
進行設置。System.getenv("ANDROID_LINT_MAX_DEPTH");
語句獲取,如何設置還沒找到。佈局
Layout
內有太多的View
:一個Layout
文件內有過多的View
會影響性能。考慮使用複合drawables或其餘技巧來減小這個佈局中的視圖數量。默認最多的數量是80個,能夠經過環境變量ANDROID_LINT_MAX_VIEW_COUNT
進行設置。聽說這個變量能夠用System.getenv("ANDROID_LINT_MAX_DEPTH");
語句獲取,如何設置還沒找到。
Weight嵌套:使用非
0
的layout-weight
值,須要Layout被測量兩次,若是一個包含非0
值的LinearLayout
被嵌套在另外一個包含非0
值的LinearLayout
內部,那麼,測量次數就會呈指數級增加。
這個主要是講RecyclerView的分割線,
com.android.support:recyclerview-v7
提供了一個類DividerItemDecoration
設置分割線樣式,這個類在早期的版本內沒有包含,因此在更新爲新的版本後,可使用這個類從新設置分割線。 具體使用,參考文章:Android RecyclerView 使用徹底解析
當
FrameLayout
在一個layout文件中是root且沒有使用background
或者padding
等屬性,一般使用一個merge
標籤代替FrameLayout
會更高效。可是這要看上下文設置,因此在替換以前要確認你已經理解了merge
標籤的工做原理。
未使用的資源:多指的是drawable類型的資源。多餘的drawable資源會讓APP變大,編譯過程變長。
當LinearLayout只有一個Widget且使用了
android:layout_weight
時,定義對應的width/height
的值爲0dp
,Widget就會自動佔滿剩餘空間。由於不須要預先計算本身的尺寸,這種方式更高效。
在使用LinearLayout實現空間的按比例分割時,LinearLayout的空間用layout_weight屬性在所包含的幾個layout中間分割,那麼應該設置被分割LinearLayout
baseLineAligned="false"
,這樣能夠加快分割空間所作的運算。
LogConditional:使用
android.util.Log
打印調試日誌,通常只會在DEBUG
模式下使用,在release
是不須要打印調試日誌的,在buildToolsVersion
大於等於17時,BuildConfig
提供兩個一個DEBUG
常量來標記是否處於DEBUG模式,咱們能夠用if(BuildConfig.DEBUG){}
包裹調試日誌語句,這樣編譯器會在編譯生成release包時,刪除這些語句。若是真的須要在release模式下打印調試日誌,可使用@SuppressLint("LogConditional")
註解告訴編譯器在release包中保留這些日誌信息。
APP使用
System.loadLibrary()
加載Native庫時,android 6.0或者更新的版本能夠在Manifest文件中application
標籤中添加屬性android:extractNativeLibs="false"
,這樣能夠提交加載速度,下降APP佔用的存儲空間。
不要使用FloatMath類進行數學計算,推薦使用Math類。
Android早期版本由於浮點運算性能的緣由,推薦使用FloatMath代替Math類進行數學計算。隨着硬件和系統的發展,這個問題已經不復存在,甚至通過JIT優化以後的Math類運算速度會比FloatMath更快,因此,在Android F以上版本的系統上,能夠直接使用Math類,而不是FloatMath。
某些類構造新對象時,建議使用工廠方法,而不是
new
關鍵字聲明新的對象。例如,new Intger(0)
就可使用Integer.valueOf(0)
替代,工廠方法會使用更少的內存,由於它會讓值相等的對象使用同一個實例。
在給
ListView
或GradView
之類的列表實現Adapter
時,不能每次getView
調用都去inflate
一個新的layout
,若是接口參數中給出了一個能夠複用的View對象,就可使用這個對象而不是從新生成。這個應該都很熟悉,也很簡單基礎了。
Key
爲Integer
類型的HashMap
可使用SparseArray
代替,性能更好。可使用替代HashMap
的有SparseBooleanArray、SparseIntArray、SparseLongArray
和泛型類SparseArray
,每一個對應的類型表明Value的類型。若是在某些狀況必定要用HashMap實現,則能夠用@SuppressLint
註解抑制Lint檢查。
關於
week lock
的使用,這裏提供一篇博客文章:Android 功耗分析之wakelock
在一個
TextView
的四周有隻具備展現做用的ImageView
時,建議刪除ImageView
改用compound drawables:drawableTop, drawableLeft, drawableRight,drawableBottom,drawablePadding
替代方案實現。
缺乏recycle()調用:許多資源例如:
TypedArrays, VelocityTrackers
在使用完以後須要調用recycle()
方法回收資源。
4.0版本系統以前,
View.setTag(int, Object)
的實現方式中,會把Object
存儲在一個靜態的map
裏而且使用的是強引用。這就意味着若是這個Object
包含了對Context
對象的引用,這個Context
就是泄漏了。
傳遞一個
View
作參數,這個View
就能提供一個對建立它的Context
的引用。相似的,View holders
內包含View
,也會有Context
與這個View
相關聯。
Handler引用泄漏:聲明Handler的子類如
MyHandler
爲內部類,若是MyHandler
類對象關聯Looper.getMainLooper()
或者Looper.getMainLooper().getQueue()
時,會阻止無用的外部類對象被垃圾回收,致使泄漏。若是對應main thread
的關聯,就不會有這個問題。
應對方法,聲明
MyHandler
爲靜態內部類,並用WeakReference
的方式持有一個外部類對象,MyHandler
使用這個對象操做外部類的屬性和方法。
繪製過程當中的內存分配:避免在佈局繪製過程當中分配內存給新的對象。由於這些操做調用頻率比較高,頻繁分配內存會喚起垃圾回收,中斷UI繪製,致使卡頓。
非靜態內部類具備對其外部類對象的隱式引用。
若是外部類Fragment
或者Activity
,那麼這個引用意味着長時間運行的處理程序/加載器/任務(handler/loader/task)將持外部類對象的引用,從而防止外部類對象被回收。
同理,長時間運行的處理程序/加載器/任務(handler/loader/task)對Fragment
或者Activity
的直接引用,也會形成泄漏。
ViewModel類應該禁止引用View或者non-application
類型的Context
對象。
屬性動畫默認支持的屬性以下面列表。若是超出這些範圍,會經過反射調用本地定義的函數。聲明一個屬性動畫對象例如:
ObjectAnimator.ofFloat(view, "rotation", 0, 360)
中的「rotation」就是要操做的屬性,若是屬性不在下面的列表中例如ObjectAnimator.ofFloat(view, "position", 0, 360)
,就須要本地定義一個對應的方法setPosition(float position)
,而且這個方法須要加上@keep
註解,防止被當作無用方法清理掉。
static {
PROXY_PROPERTIES.put("alpha", PreHoneycombCompat.ALPHA);
PROXY_PROPERTIES.put("pivotX", PreHoneycombCompat.PIVOT_X);
PROXY_PROPERTIES.put("pivotY", PreHoneycombCompat.PIVOT_Y);
PROXY_PROPERTIES.put("translationX", PreHoneycombCompat.TRANSLATION_X);
PROXY_PROPERTIES.put("translationY", PreHoneycombCompat.TRANSLATION_Y);
PROXY_PROPERTIES.put("rotation", PreHoneycombCompat.ROTATION);
PROXY_PROPERTIES.put("rotationX", PreHoneycombCompat.ROTATION_X);
PROXY_PROPERTIES.put("rotationY", PreHoneycombCompat.ROTATION_Y);
PROXY_PROPERTIES.put("scaleX", PreHoneycombCompat.SCALE_X);
PROXY_PROPERTIES.put("scaleY", PreHoneycombCompat.SCALE_Y);
PROXY_PROPERTIES.put("scrollX", PreHoneycombCompat.SCROLL_X);
PROXY_PROPERTIES.put("scrollY", PreHoneycombCompat.SCROLL_Y);
PROXY_PROPERTIES.put("x", PreHoneycombCompat.X);
PROXY_PROPERTIES.put("y", PreHoneycombCompat.Y);
}
複製代碼
無用的SDK版本檢查:Android SDK的版本更新比較快,許多API的使用都須要經過檢查SDK版本防止出現not found之類的崩潰。在APP迭代的過程當中提高了
minSdkVersion
的值就會致使部分SDK版本檢查再也不須要。
這種SDK版本檢查會引發沒必要要的資源搜索。
之前,文檔中建議在productFlavors中建立一個dev product。設定
minSdkVersion 21
,在開發過程當中激活multidexing加速構建過程。如今已經不須要這麼作了,在新版的IDE和Gradle插件中,會自動地識別所鏈接設備的API level,若是連接的設備API level大於等於21,就會自動打開multindexing,就跟以前設置了dev product的效果同樣。
無用的LayoutParam:當給Widget使用了所在Layout沒有提供的LayouParam時,會有這個提示。這種狀況通常出如今修改Layout類型時沒有同時修改內部Widget的LayoutParam設置或者把一個Widget從一個Layout拷貝到另外一個不一樣類型的Layout內部。
這種無用的LayoutParam在運行時會引發無效的屬性解析,也會誤導閱讀這些代碼的人。因此應該把這些無用的屬性刪除掉。