本周有個需求近忙,對某個界面進行優(yōu)化宦赠,然后看了一些文章,并進行小結(jié),為了方便以后回頭查看蝇庭。
僅供個人參考
一呈础、界面繪制優(yōu)化
1. 頁面卡頓原因
- 布局 Layout 過于復(fù)雜耸三,無法在16 ms 內(nèi)完成渲染澎埠。
- 同一時間動畫執(zhí)行的次數(shù)過多,導(dǎo)致 CPU 或 GPU 負載過重
- View 過度繪制溶弟,導(dǎo)致某些像素在同一幀時間內(nèi)被繪制多次
- UI 線程中做了稍微耗時的操作
2. 解決工具
- 開發(fā)者選項-打開GPU渲染
- 使用
Systrace
- 使用
TraceView
- 使用
Hierarchy Viewer
觀察每個 View 的繪制時間
3. 解決策略
- 如果布局層數(shù)比較多的時候女淑,推薦使用 RelativeLayout
- 如果布局嵌套比較多,推薦使用 LinearLayout (RelativeLayout 的view的排列方式是基于彼此于彼此依賴)
- 使用 include 標(biāo)簽進行布局復(fù)用
- 使用 merge 標(biāo)簽去除多余層級
- merge 標(biāo)簽最好是替代 FrameLayout 或者是布局一致的 LinearLayout辜御,比如當(dāng)前布局的 LinearLayout 是垂直方向的鸭你,被包含的布局的 LinearLayout 也是垂直方向的則可以使用 merge 標(biāo)簽。
- 使用 ViewStub 延遲加載布局提高加載速度
- ViewStub 只能加載一次擒权,加載后 ViewStub 被置為空
- ViewStub 不能嵌套 merge 標(biāo)簽
- ViewStub 操作的是布局文件袱巨,如果想操作具體的 view,還是要使用 view 的visible 屬性
- 避免過度繪制碳抄、重繪
- 移除不需要的 background
- 在自定義 view 的 onDraw 方法中愉老,用 canvas.clipRect 來指定繪制的區(qū)域,放置重疊的組件發(fā)生過度繪制
二纳鼎、內(nèi)存泄露
1. 主要原因分類
- 開發(fā)人員自己編寫代碼造成的內(nèi)存泄漏
- 第三方框架造成的泄漏
- 由 Android 系統(tǒng)或者第三方 ROM 造成的內(nèi)存泄漏
2. 泄露場景
- 非靜態(tài)內(nèi)部類的靜態(tài)實例
- 如果非靜態(tài)內(nèi)部類里面創(chuàng)建的實例是靜態(tài)的俺夕,那么它會間接的長期維持著外部的引用裳凸,阻止被系統(tǒng)回收
- 匿名內(nèi)部類的靜態(tài)實例
- Handler 的內(nèi)存泄露
- 如果 Handler 是非靜態(tài)的贱鄙,那么 Handler 也會導(dǎo)致引用它的 Activity劝贸、Service or Fragment,導(dǎo)致內(nèi)存泄露
- 未正確使用 Context (最常見的就是單例模式)
- 靜態(tài)的 view
- 資源對象未關(guān)閉(curson file)
- 集合中對象未清理
- Bitmap 對象
- 避免靜態(tài)變量持有比較大的 btimap 對象或者其他大的數(shù)據(jù)對象逗宁,如果已持有映九,要盡快置空靜態(tài)變量
- 監(jiān)聽器未關(guān)閉
- 很多系統(tǒng)的服務(wù) TelephonyManager SensorManager 記得取消注冊,或者注冊 null
三瞎颗、開發(fā)過程中遵循的守則
1. 編程思想
應(yīng)用層的性能優(yōu)化通臣可以從以下幾個方面考慮:
- 了解編程語言的編譯原理,使用高效編碼方式從語法上提高程序性能哼拔;
- 采用合理的數(shù)據(jù)結(jié)構(gòu)和算法提高程序性能引有,這往往是決定程序性能的關(guān)鍵;
- 重視界面布局優(yōu)化倦逐;
- 采用多線程譬正、緩存數(shù)據(jù)、延遲加載檬姥、提前加載等手段曾我,解決嚴重的性能瓶頸;
- 合理配置虛擬機堆內(nèi)存使用上限和使用率健民,減少垃圾回收頻率抒巢;
- 合理使用native代碼;
- 合理配置數(shù)據(jù)庫緩存類型和優(yōu)化SQL語句加快讀取速度秉犹,使用事務(wù)加快寫入速度蛉谜;
- 使用工具分析性能問題,找出性能瓶頸崇堵;
2. 編程技巧
不執(zhí)行不必要的操作(CPU)悦陋、不分配不必要的內(nèi)存(內(nèi)存)
- 避免創(chuàng)建不必要的對象
- 分配內(nèi)存本身需要時間,虛擬機運行時堆內(nèi)存使用量是有上限的筑辨,容易出發(fā) GC俺驶,使進程暫停,造成嚴重卡頓棍辕。
- 合理使用 static 成員
- 不需要操作運行時的動態(tài)變量和方法暮现,那么可以講方法設(shè)置為 static
- 常量字段要聲明為 static final,因為常量會被放在 dex 文件的靜態(tài)字段初始化器中被直接訪問楚昭。否在運行時會通過編譯器自動生成一些函數(shù)來初始化此規(guī)則只對基本類型和 String 類型有效
- 避免創(chuàng)建 static 的 view or context栖袋,持有 Activity 的引用容易造成內(nèi)存泄露
- 避免內(nèi)部的 getter 和 setter
- 盡量直接聲明為 public,直接訪問的速度比間接訪問要快7倍
- 合理使用浮點類型
- 在 Android 設(shè)備中抚太,浮點型大概比整形數(shù)據(jù)處理速度慢兩倍
- 移除 Activity 默認背景塘幅,提升 Activity 加載速度
getWindow().setBackgroundDrawable(null);
- cursor stream 的關(guān)閉
- 廣播的注冊和取消注冊
- 合理使用
StringBuffer
StringBuilder
String
- 盡量使用局部變量
- 調(diào)用方法時傳遞的參數(shù)已經(jīng)調(diào)用中創(chuàng)建的臨時變量都保存在 stack 中昔案,速度較快,其他變量(靜態(tài)變量电媳、成員變量)都在 heap 中創(chuàng)建踏揣,速度較慢
- IntentService 代替 Service
- 使用
ApplicationCotext
代替 Activity 的 Context - 集合中的對象及時清理
- 記得在
onDestory()
方法中,及時銷毀 webView