本周有個(gè)需求,對(duì)某個(gè)界面進(jìn)行優(yōu)化,然后看了一些文章,并進(jìn)行小結(jié),為了方便以后回頭查看。

僅供個(gè)人參考

我還可以繼續(xù)戰(zhàn)斗
一、界面繪制優(yōu)化
1. 頁(yè)面卡頓原因
- 布局 Layout 過(guò)于復(fù)雜,無(wú)法在16 ms 內(nèi)完成渲染。
- 同一時(shí)間動(dòng)畫(huà)執(zhí)行的次數(shù)過(guò)多,導(dǎo)致 CPU 或 GPU 負(fù)載過(guò)重
- View 過(guò)度繪制,導(dǎo)致某些像素在同一幀時(shí)間內(nèi)被繪制多次
- UI 線程中做了稍微耗時(shí)的操作
2. 解決工具
- 開(kāi)發(fā)者選項(xiàng)-打開(kāi)GPU渲染
- 使用
Systrace - 使用
TraceView - 使用
Hierarchy Viewer觀察每個(gè) View 的繪制時(shí)間
3. 解決策略
- 如果布局層數(shù)比較多的時(shí)候,推薦使用 RelativeLayout
- 如果布局嵌套比較多,推薦使用 LinearLayout (RelativeLayout 的view的排列方式是基于彼此于彼此依賴)
- 使用 include 標(biāo)簽進(jìn)行布局復(fù)用
- 使用 merge 標(biāo)簽去除多余層級(jí)
- merge 標(biāo)簽最好是替代 FrameLayout 或者是布局一致的 LinearLayout,比如當(dāng)前布局的 LinearLayout 是垂直方向的,被包含的布局的 LinearLayout 也是垂直方向的則可以使用 merge 標(biāo)簽。
- 使用 ViewStub 延遲加載布局提高加載速度
- ViewStub 只能加載一次,加載后 ViewStub 被置為空
- ViewStub 不能嵌套 merge 標(biāo)簽
- ViewStub 操作的是布局文件,如果想操作具體的 view,還是要使用 view 的visible 屬性
- 避免過(guò)度繪制、重繪
- 移除不需要的 background
- 在自定義 view 的 onDraw 方法中,用 canvas.clipRect 來(lái)指定繪制的區(qū)域,放置重疊的組件發(fā)生過(guò)度繪制
二、內(nèi)存泄露
1. 主要原因分類
- 開(kāi)發(fā)人員自己編寫(xiě)代碼造成的內(nèi)存泄漏
- 第三方框架造成的泄漏
- 由 Android 系統(tǒng)或者第三方 ROM 造成的內(nèi)存泄漏
2. 泄露場(chǎng)景
- 非靜態(tài)內(nèi)部類的靜態(tài)實(shí)例
- 如果非靜態(tài)內(nèi)部類里面創(chuàng)建的實(shí)例是靜態(tài)的,那么它會(huì)間接的長(zhǎng)期維持著外部的引用,阻止被系統(tǒng)回收
- 匿名內(nèi)部類的靜態(tài)實(shí)例
- Handler 的內(nèi)存泄露
- 如果 Handler 是非靜態(tài)的,那么 Handler 也會(huì)導(dǎo)致引用它的 Activity、Service or Fragment,導(dǎo)致內(nèi)存泄露
- 未正確使用 Context (最常見(jiàn)的就是單例模式)
- 靜態(tài)的 view
- 資源對(duì)象未關(guān)閉(curson file)
- 集合中對(duì)象未清理
- Bitmap 對(duì)象
- 避免靜態(tài)變量持有比較大的 btimap 對(duì)象或者其他大的數(shù)據(jù)對(duì)象,如果已持有,要盡快置空靜態(tài)變量
- 監(jiān)聽(tīng)器未關(guān)閉
- 很多系統(tǒng)的服務(wù) TelephonyManager SensorManager 記得取消注冊(cè),或者注冊(cè) null
三、開(kāi)發(fā)過(guò)程中遵循的守則
1. 編程思想
應(yīng)用層的性能優(yōu)化通常可以從以下幾個(gè)方面考慮:
- 了解編程語(yǔ)言的編譯原理,使用高效編碼方式從語(yǔ)法上提高程序性能;
- 采用合理的數(shù)據(jù)結(jié)構(gòu)和算法提高程序性能,這往往是決定程序性能的關(guān)鍵;
- 重視界面布局優(yōu)化;
- 采用多線程、緩存數(shù)據(jù)、延遲加載、提前加載等手段,解決嚴(yán)重的性能瓶頸;
- 合理配置虛擬機(jī)堆內(nèi)存使用上限和使用率,減少垃圾回收頻率;
- 合理使用native代碼;
- 合理配置數(shù)據(jù)庫(kù)緩存類型和優(yōu)化SQL語(yǔ)句加快讀取速度,使用事務(wù)加快寫(xiě)入速度;
- 使用工具分析性能問(wèn)題,找出性能瓶頸;
2. 編程技巧
不執(zhí)行不必要的操作(CPU)、不分配不必要的內(nèi)存(內(nèi)存)
- 避免創(chuàng)建不必要的對(duì)象
- 分配內(nèi)存本身需要時(shí)間,虛擬機(jī)運(yùn)行時(shí)堆內(nèi)存使用量是有上限的,容易出發(fā) GC,使進(jìn)程暫停,造成嚴(yán)重卡頓。
- 合理使用 static 成員
- 不需要操作運(yùn)行時(shí)的動(dòng)態(tài)變量和方法,那么可以講方法設(shè)置為 static
- 常量字段要聲明為 static final,因?yàn)槌A繒?huì)被放在 dex 文件的靜態(tài)字段初始化器中被直接訪問(wèn)。否在運(yùn)行時(shí)會(huì)通過(guò)編譯器自動(dòng)生成一些函數(shù)來(lái)初始化此規(guī)則只對(duì)基本類型和 String 類型有效
- 避免創(chuàng)建 static 的 view or context,持有 Activity 的引用容易造成內(nèi)存泄露
- 避免內(nèi)部的 getter 和 setter
- 盡量直接聲明為 public,直接訪問(wèn)的速度比間接訪問(wèn)要快7倍
- 合理使用浮點(diǎn)類型
- 在 Android 設(shè)備中,浮點(diǎn)型大概比整形數(shù)據(jù)處理速度慢兩倍
- 移除 Activity 默認(rèn)背景,提升 Activity 加載速度
getWindow().setBackgroundDrawable(null);
- cursor stream 的關(guān)閉
- 廣播的注冊(cè)和取消注冊(cè)
- 合理使用
StringBufferStringBuilderString - 盡量使用局部變量
- 調(diào)用方法時(shí)傳遞的參數(shù)已經(jīng)調(diào)用中創(chuàng)建的臨時(shí)變量都保存在 stack 中,速度較快,其他變量(靜態(tài)變量、成員變量)都在 heap 中創(chuàng)建,速度較慢
- IntentService 代替 Service
- 使用
ApplicationCotext代替 Activity 的 Context - 集合中的對(duì)象及時(shí)清理
- 記得在
onDestory()方法中,及時(shí)銷毀 webView