前言
今天逛稀土?xí)r偶然看到hanks分享的一篇英文文章,粗略瀏覽便已覺(jué)得不錯(cuò)鼻忠,因此翻譯成中文,與君分享。
原文地址:Android Performance Patterns: Rescue tips
正文
現(xiàn)在的app到處都充斥著華麗的動(dòng)畫粘捎、復(fù)雜的轉(zhuǎn)化還有自定義View,然而用戶體驗(yàn)必須盡可能直觀且類似危彩。以下這些范例將會(huì)幫助你做出一個(gè)流暢的攒磨、快速響應(yīng)的、甚至可能減少電量損耗的app恬砂,這些范例由一些可以提升整體應(yīng)用表現(xiàn)的微優(yōu)化組成咧纠。
避免“壞”表現(xiàn)
- 避免堵塞主線程
- 避免可能引發(fā)大范圍重繪的不必要的重繪
- 用
RelativeLayout
來(lái)減少布局層級(jí) - 避免在
LinearLayout
中使用嵌套的 weight 屬性(因?yàn)閣eight屬性會(huì)使每個(gè)子View進(jìn)行兩次measure) - 避免使用沒(méi)有恰當(dāng)處理的自定義View
- 避免創(chuàng)建沒(méi)必要的對(duì)象
- 將常量聲明為 static final(static比普通變量快 15% - 20%)
- 使用基本數(shù)據(jù)類型(Integer、Float 比基本類型慢兩倍)
- 避免內(nèi)部的
getter
和setter
(直接訪問(wèn)屬性可以快3倍) - 使用改進(jìn)的循環(huán)語(yǔ)法【譯者注:這里應(yīng)該是指for each循環(huán)】
- 對(duì)私有的內(nèi)部類考慮使用包訪問(wèn)級(jí)別代替私有訪問(wèn)級(jí)別
- 謹(jǐn)慎使用native方法
自定義View
- 遵循KISS原則
- 在布局中使用
merge
標(biāo)簽來(lái)作為根標(biāo)簽(避免額外的ViewGroup
) - 使用
include
標(biāo)簽(便于布局的復(fù)用) - 避免不必要的布局
- 不要在
onDraw
中申請(qǐng)內(nèi)存或者做復(fù)雜邏輯 - 去除不必要的
invalidate()
調(diào)用 - 考慮創(chuàng)建自己的
ViewGroup
- 用
RecyclerView
替代ListView
和GridView
避免內(nèi)存抖動(dòng)
- 不要申請(qǐng)大量不必要的對(duì)象內(nèi)存:
1, 不可變對(duì)象:String
2, 自動(dòng)裝箱:Integer, Boolean... - 考慮使用對(duì)象池并緩存來(lái)減少內(nèi)存抖動(dòng)
- 留心
enum
類型的開(kāi)銷(一個(gè)指向枚舉類型的引用就要占據(jù)4個(gè)字節(jié))
避免內(nèi)存泄漏
- 不要在內(nèi)部類里泄漏context實(shí)例
- 不要在
activity
里泄漏view實(shí)例 - 使用內(nèi)部靜態(tài)類優(yōu)于非靜態(tài)的
- 除非鍵都是
WeakReference
泻骤,否則不要使用WeakHashmap
作為緩存
CPU
- 不要嵌套多通路布局
- 當(dāng)需要時(shí)才去進(jìn)行復(fù)雜的計(jì)算【譯者注:類似懶加載】
- 緩存復(fù)雜計(jì)算的結(jié)果以復(fù)用
- 考慮
RenderScript
的性能 - 盡可能減少主線程的工作
避免過(guò)度繪制
- 精簡(jiǎn)
drawable
- 在透明部分使用.9圖
- 設(shè)置view的透明度時(shí)多注意
- 去除view中無(wú)用的背景
bitmap
- 將bitmap解碼為需要的尺寸:
BitmapFactory.Options( inSampleSize, inDensity, inTargetDensity)
- 加載bitmap到內(nèi)存時(shí)漆羔,設(shè)置尺寸為顯示尺寸
- 如無(wú)必要不要進(jìn)行縮放
- 使用
LRU
緩存
Service
- 除非Service在處理事務(wù)否則不要讓其保持運(yùn)行。同時(shí)也要小心
stopService
當(dāng)Service工作完成時(shí) - 系統(tǒng)傾向保留有Service運(yùn)行的進(jìn)程狱掂,那么被service占用的內(nèi)存將無(wú)法被其他進(jìn)程使用或者被內(nèi)存置換
- 限制service生命周期的最佳實(shí)踐是使用
IntentService
演痒,它會(huì)在工作完成后結(jié)束自身 - 讓沒(méi)必要存活的Service繼續(xù)運(yùn)行是Android app內(nèi)存管理最差的舉動(dòng)之一
線程
- 在線程的
run()
方法中使用Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND)
可以減少該線程及UI線程的計(jì)算性能損耗 - 如果你沒(méi)有通過(guò)這種方式為線程設(shè)置低優(yōu)先級(jí),那么該線程仍會(huì)拖慢你的app趋惨,因?yàn)槟J(rèn)情況下它的優(yōu)先級(jí)與UI線程的優(yōu)先級(jí)相同
- 維護(hù)住當(dāng)前線程的引用鸟顺,以便你之后可能先打斷該線程。例如:當(dāng)網(wǎng)絡(luò)連接失敗你可以取消該線程
避免ANR
- UI線程中做的事越少越好
- 如果應(yīng)用正在后臺(tái)響應(yīng)用戶的輸入器虾,最好顯示進(jìn)度給用戶(例如顯示一個(gè)進(jìn)度條)
- 使用Systrace或Traceview等性能工具來(lái)檢測(cè)應(yīng)用響應(yīng)能力的瓶頸
- 如果你的應(yīng)用有一個(gè)非常耗時(shí)的初始化過(guò)程讯嫂,考慮使用啟動(dòng)頁(yè)或者盡快渲染主要的view,表明正在加載中并且正在顯示異步的信息