一. 布局優(yōu)化
核心思想:減少布局文件層級(jí)
布局層級(jí)減少 -> 繪制工作量減少 ->性能提高
- 刪除布局中無用控件和層級(jí)
- 有選擇的使用ViewGroup
- 優(yōu)先使用 LinearLayout 和 FrameLayout
- 需要嵌套時(shí)使用 RelativeLayout(減少層級(jí))
- <include> 重用布局
- <merge> + <include> 減少層級(jí)
- <ViewStub> 按需加載备埃,提高初始化性能
二. 繪制優(yōu)化
核心思想:View 的 onDraw 方法避免執(zhí)行大量操作,因?yàn)?onDraw 方法可能會(huì)被頻繁調(diào)用胧弛。
- 避免創(chuàng)建新的局部對(duì)象:大量臨時(shí)對(duì)象占用內(nèi)存且導(dǎo)致頻繁 gc
- 不要做耗時(shí)任務(wù)和循環(huán):造成 View 繪制過程不流暢
三. 內(nèi)存泄漏優(yōu)化
核心思想:經(jīng)驗(yàn) + 工具
- 開發(fā)中避免寫出有內(nèi)存泄漏的代碼
- 通過分析工具找出潛在內(nèi)存泄漏并解決
避免寫出有內(nèi)存泄漏的代碼
Activity 被靜態(tài)變量、靜態(tài)集合猎唁、單例對(duì)象引用導(dǎo)致其無法及時(shí)銷毀
-
屬性動(dòng)畫:
無限循環(huán)動(dòng)畫持有 View罚舱,而View持有 Activity導(dǎo)致其無法釋放(Activity 銷毀時(shí)候調(diào)用animator.cancel()停止動(dòng)畫
-
Handler 導(dǎo)致的內(nèi)存泄漏:
被延時(shí)處理的 Message 持有 Handler 的引用蛀醉,非靜態(tài)Handler 隱式持有對(duì) Activity 的引用,形成了message – handler – activity 這樣一條引用鏈,使得引用關(guān)系會(huì)保持至消息得到處理藤违,導(dǎo)致 Activity 的泄漏浪腐。
解決方案:- 靜態(tài)內(nèi)部類Handler + WeakReference(弱引用Activity)
- Activity 銷毀時(shí)候清空所有消息:handler.removeCallbacksAndMessages(null);
盡量用ApplicationContext 而不是 Activity Context
-
線程導(dǎo)致的內(nèi)存泄漏
Thread/AsyncTask 這類線程任務(wù),若以內(nèi)部類的方式存在顿乒,隱式持有Activity议街,當(dāng)Activity銷毀時(shí)線程任務(wù)還未執(zhí)行完畢(run/doInbackground)則內(nèi)部類不會(huì)被銷毀,因此它引用的Activity也不會(huì)銷毀導(dǎo)致泄露璧榄。
解決方案:- 線程內(nèi)部類使用靜態(tài)內(nèi)部類
- 在線程內(nèi)部采用弱引用保存 Activity 引用
-
及時(shí)關(guān)閉/釋放資源
- BraodcastReceiver 及時(shí)調(diào)用 unRegister()注銷
- Cursor特漩、File、Stream 及時(shí)調(diào)用 close ()關(guān)閉
工具
- MAT
- LeakCanary
四. 響應(yīng)速度優(yōu)化
核心思想:避免在主線程執(zhí)行耗時(shí)操作
- 異步執(zhí)行耗時(shí)任務(wù)
- ANR 日志分析:/data/anr/traces.txt
五. ListView優(yōu)化
核心思想:復(fù)用+減少耗時(shí)操作
- 復(fù)用 convertView:減少加載布局文件的次數(shù)(耗時(shí))
- 使用 ViewHolder:減少 findViewById的次數(shù)(耗時(shí))
- 避免在 getView 中執(zhí)行耗時(shí)操作
- 列表滑動(dòng)時(shí)暫停加載骨杂、空閑時(shí)執(zhí)行加載
六. Bitmap優(yōu)化
核心思想:降低圖片占用內(nèi)存大小
BitmapFactory根據(jù)實(shí)際控件大小對(duì)圖片進(jìn)行采樣涂身,用到 BitmapFactory.Options 的 insimpleSize 和 inJustDecodeBounds 參數(shù)
純色盡量使用color;規(guī)則圖形盡量用shape搓蚪;稍微復(fù)雜使用9patch圖蛤售;如果不能使用9patch針對(duì)幾種主流分辨率機(jī)型進(jìn)行切圖。
七. 線程優(yōu)化
核心思想:線程池
ThreadPoolExecutor: 實(shí)現(xiàn)了 Executor 接口
執(zhí)行規(guī)則: 核心線程->任務(wù)隊(duì)列->非核心線程->拒絕執(zhí)行異常
- 線程池中線程數(shù)量未達(dá)到核心線程數(shù)時(shí)妒潭,會(huì)直接啟動(dòng)一個(gè)核心線程來執(zhí)行任務(wù)
- 若已達(dá)到或超出核心線程數(shù)量悴能,那么任務(wù)會(huì)被插入到任務(wù)隊(duì)列中排隊(duì)等待執(zhí)行
- 若任務(wù)隊(duì)列中無法插入(已滿),且線程數(shù)量未達(dá)到線程池規(guī)定的最大值雳灾,會(huì)立即啟動(dòng)一個(gè)非核心線程來執(zhí)行
- 若步驟3中線程數(shù)量已達(dá)到線程池規(guī)定的最大值會(huì)拒絕執(zhí)行此任務(wù)漠酿,會(huì)調(diào)用RejectedExecutionHandler的rejectExecution方法來通知調(diào)用者
構(gòu)造參數(shù)含義:
- corePoolSize:核心線程數(shù),默認(rèn)核心線程會(huì)一直存活即使空閑
- maximumPoolSize:最大線程數(shù)佑女,當(dāng)活動(dòng)線程數(shù)達(dá)到這個(gè)數(shù)值后,后續(xù)的新任務(wù)會(huì)被阻塞
- keepAliveTime:非核心線程閑置時(shí)的超時(shí)時(shí)長谈竿,超過這個(gè)時(shí)長团驱,非核心線程就會(huì)被回收
- unit:用于指定 keepAliveTime 參數(shù)的時(shí)間單位
- workQueue:線程池中的任務(wù)隊(duì)列,通過線程池的 execute 方法提交的 Runnable 對(duì)象 會(huì)存儲(chǔ)在這個(gè)參數(shù)中
- threadFactory:線程工廠空凸,為線程池提供創(chuàng)建新線程的功能嚎花。該接口只有一個(gè)方法:newThread(Runnable r)
- RejectedExecutionHandler:當(dāng)線程池?zé)o法執(zhí)行執(zhí)行新任務(wù)時(shí)(任務(wù)隊(duì)列已滿或無法成功執(zhí)行任務(wù))這時(shí) ThreadPoolExecutor 會(huì)調(diào)用 handler 的 rejectedExecution 方法來通知調(diào)用者,默認(rèn)該方法會(huì)直接拋出一個(gè) RejectedExecutionException呀洲。
分類:
-
SingleThreadExecutor
只有一個(gè)核心線程紊选,可確保任務(wù)都在同一個(gè)線程中按順序執(zhí)行,不需要處理線程同步問題 -
FixedThreadPool
線程數(shù)量固定道逗,只有核心線程且線程空閑時(shí)不會(huì)被回收(除非線程池被關(guān)閉)兵罢,因此可更快響應(yīng)外界請(qǐng)求。 -
CacheThreadPool
線程數(shù)量不定滓窍,只有非核心線程(最大線程數(shù)為Integer.MAX_VALUE)卖词,空閑線程超時(shí)回收機(jī)制;適合執(zhí)行大量耗時(shí)較少的任務(wù)吏夯。 -
ScheduledThreadPool
核心線程數(shù)量固定此蜈,非核心線程數(shù)量無限制空閑時(shí)立即回收即横;主要用于執(zhí)行定時(shí)任務(wù)和固定周期的重復(fù)任務(wù)。
八. 一些優(yōu)化建議
- 避免創(chuàng)建過多的對(duì)象
- 整型優(yōu)先于枚舉
- 常量使用 static final 修飾
- 使用一些 Android 特有的數(shù)據(jù)結(jié)構(gòu)裆赵,如 SparseArray和Pair等
- 適當(dāng)使用軟引用和弱引用
- 采用內(nèi)存緩存和磁盤緩存
- 盡量采用靜態(tài)內(nèi)部類东囚,避免潛在的內(nèi)存泄漏
- 頻繁字符串拼接用StringBuilder
- 合理使用 static
static聲明變量的生命周期和 App 的生命周期一樣的,大量的使用,會(huì)占據(jù)內(nèi)存空間不釋放战授,積少成多會(huì)造成內(nèi)存的不斷開銷页藻,直至掛掉;
一般用來修飾基本數(shù)據(jù)類型或者輕量級(jí)對(duì)象,盡量避免修復(fù)集合或者大對(duì)象陈醒,常用作修飾全局配置項(xiàng)惕橙、工具類方法、內(nèi)部類钉跷。