一.何為App的效能
拿小車舉例,大家知道什麼是一輛小車的效能嗎?同學甲說,是否省油、加速是否夠快、開起來是否穩定、安全等等。
沒錯,那就是小車的效能。
那App的效能又是指什麼呢?同學乙說,App啟動是否夠快,執行是否流暢,是否省電、省流量,安裝包體積是否夠小等等。
是的,這就是App的效能。
二.關注App效能,有什麼用
我們知道,一輛小車效能越好,加速越快,跑的越穩,越省油。
App也一樣,效能越好,執行更流暢、更穩定、更省流量、電量,包的體積也會更小,這能給使用者帶來優秀的體驗,進而也會提升App的知名度。
既然App效能那麼重要,那我們就要掌握App效能優化的技能了。
三.如何進行App效能優化
掌握App效能優化,是Android開發人員進階中高階的必備技能。那如何進行App的效能優化呢?
我們可以從這幾個方面入手:卡頓優化、記憶體優化、穩定性優化、耗電優化、安裝包大小優化、資料庫SQLite優化、網路優化。
接下來,我們逐一展開講解。
1.卡頓優化
1.1卡頓場景
可分為四個大的方向:
1.1.1UI
UI包括繪製和渲染。
1.1.2啟動
啟動可分為冷啟動、熱啟動。
1.1.3跳轉
跳轉包括頁面間跳轉和前後臺切換。
1.1.4響應
包括:點選、滑動、系統事件、按鍵。
1.2卡頓原因
可分為以下兩方面原因:
1.2.1繪製任務太重
首先,我們要明白這樣一個概念,人類肉眼在看每秒60幀(即:每幀16ms)的畫面時,是不會感受畫面卡頓,當低於60幀/秒,我們就會感受到畫面卡頓了。
Android系統每隔16ms就發出Vsync,觸發對UI的渲染。如果每次都在<=16ms內完成渲染,介面就會流暢;如果每次都在>16ms才能完成渲染,就會造成丟幀,介面就會卡頓。
1.2.2主執行緒耗時操作
主要包括資料處理耗時,資料處理佔用CPU過高,記憶體增加導致頻繁GC等。
1.3分析工具
Hierarchy View,Profile GPU Rendering,TraceView,Systrace
1.4優化手段
1.4.1佈局優化
減少佈局層級巢狀,佈局複用,刪除無用屬性,使用ViewStub提高顯示速度。
1.4.2避免過度繪製
常用佈局的優化,自定義View的優化。
1.4.3啟動優化
UI佈局,邏輯載入優化,資料準備策略優化。
1.4.4合理的重新整理機制
減少重新整理次數,縮小重新整理區域,避免後臺有較高的CPU執行緒執行。
其他:比如,使用動畫效果,根據不同場景選擇合適的動畫框架實現。有些情況,可以使用硬體加速來提高流暢度。
2.記憶體優化
2.1Android記憶體管理機制
Android應用都是在Android虛擬機器上執行的,記憶體分配和垃圾回收都是由Android虛擬機器來完成的。
2.1.1Java物件的宣告週期
建立-使用-銷燬(包括:不可見-不可達-收集-終結-物件再分配)。
Android系統記憶體分配,實際上是對堆的分配和釋放。
2.1.2記憶體回收機制
年輕代、老年代、持久代。
年輕代
所有新生成的物件都放在年輕代。
年輕代分為一個Eden區和兩個Survivor區。
GC時,當Eden區滿時,還存活的物件會被複制到其中一個Survivor區(A)。
當這個Survivor區(A)也滿時,就會被複制到另一個Survivor區(B)。
當Survivor區(B)也滿時,從第一個Survivor(B)複製過來並且還存活的物件,就會被複制到老年代。
老年代
在年輕代經歷了N次垃圾回收仍然存活的到物件,就被放到老年代。
持久代
主要存放靜態檔案,比如Java類,方法等。
持久代對垃圾回收沒有明顯影響。
如果持久代空間太小,可通過-XX:MaxPermSize =< N配置。
2.2記憶體洩露場景
資源類的物件未關閉。
註冊系統事件未登出:使用Sensor Manager等系統服務,Context.getSystemService(int name)獲取系統服務。
類的靜態變數持有大資料物件:如,activity的靜態變數持有該activty的引用。
非靜態內部類的靜態例項。
Handler造成記憶體洩漏。
WebView。
匿名類:new AsyncTask,new Thead,TimerTask。這些匿名類物件結束之前一直持有對應activity的引用,導致activity例項無法被回收,造成記憶體洩漏。
2.3分析工具
Memory Monitor,Heap Viewer,Allocation Tracker,Memory Analyzer Tool,LeakCanary。
2.4優化手段
2.4.1物件引用
根據實際需求,合理使用強引用,軟引用,弱引用,虛引用。
2.4.2減少不必要的記憶體開銷
增加記憶體複用:比如合理使用系統自帶的資源,檢視,圖片,物件池等的複用。
留意自動裝箱。
2.4.3使用最優資料型別
使用最優資料型別,比如使用ArrayMap,避免使用列舉型別,使用LruCache等。
2.4.5圖片記憶體優化
圖片壓縮,圖片快取。
3.穩定性優化
3.1異常場景
Crash,ANR。
3.2分析工具
穩定性主要依賴程式碼優化,邏輯實現的優化來提升。所以從程式碼層面來看,分析工具主要有:Android Lint,Findbugs,Checkstyle,PMD,FireLine。
3.3優化手段
3.3.1提高程式碼質量。
3.3.2程式碼掃描。
3.3.3Crash監控。
3.3.4Crash上報機制。
4.耗電優化
4.1耗電後果
App耗電嚴重,會給使用者帶來非常差的體驗,導致使用者解除安裝應用。
4.2優化手段
4.2.1Battery Historian
這是Google出的Android系統電量分析工具。
4.2.2計算優化
避免浮點運算等等。
4.2.3避免WakeLock不當使用。
4.2.4使用Job Schedule。
5.安裝包大小優化
5.1優化體積大小的原因
節省流量,提高使用者對App的好感度。
5.2優化手段及工具
5.2.1程式碼混淆
使用ProGuard工具進行壓縮,優化,混淆。ProGuard的原理:壓縮,優化,混淆。
5.2.2資源優化
使用Android Lint刪除冗餘資源,使資原始檔最小化。
5.2.3圖片優化
使用AAPT,TinyPng壓縮圖片,使用webP圖片格式等。
5.2.4避免引入重複功能的庫
對比選擇最優庫,不要引入多個類似功能的庫。如果有相關庫的原始碼,可根據實際需求,抽取需要的程式碼重新編譯庫,讓庫儘可能的小。
5.2.5外掛化
可將功能模組放伺服器,需要用時再載入。
文章APK極限壓縮:
6.資料庫SQLite優化
6.1優化手段
6.1.1索引
概念:
索引是對資料庫表中一列或多列資料進行排序的一種資料結構。可理解為一個指向表中資料的指標,與一本書的目錄類似。
優點:
加快表中資料查詢速度。
缺點:
建立索引本身也會造成資源開銷。
類別:
表索引:CREATE INDEX index_name ON table_name。
單列索引:CREATE INDEX index_name ON table_name(column_name)。
唯一索引:CREATE UNIQUE INDEX index_name ON table_name(column_name)。
組合索引:CREATE INDEX index_name ON table_name(column1,column2)。
主鍵索引:ALTER TABLE table_name ADD CONSTRAINT index_name PRIMARY KEY(primaryKey)。
總結:
合理使用索引,可加快資料庫表資料的查詢速率。
6.1.2事務
概念:
對資料庫原子性的操作。
優點:
為資料的整體性執行帶來可靠安全性,為更新和刪除操作帶來很大優化。
總結:
保證資料的完整性,安全性,提高資料更新,刪除操作的效率。
6.1.3其他手段
儘量少用cursor.getColumnIndex()。
用StringBuilder(非執行緒安全)或StringBuffer(執行緒安全)來拼接字串。
查詢時,只返回需要的資料或結果。
cursor使用後要及時關閉。
7.網路優化
7.1原因
網路優化不好,造成使用者流量消耗大,耗電快,使用者等待時間長體驗差等。
7.2工具
Network Monitor,Charles,Fiddler,Stecho。
7.3優化手段
7.3.1介面設計
API設計要合理。
使用GZIP壓縮。
選擇合適的資料格式:json,xml,protocol Buffer。
7.3.2圖片處理
圖片下載:
使用縮圖。
使用WebP圖片。
根據裝置規格,指定圖片尺寸請求圖片。
使用完善的合適的圖片載入框架:Glide,Picasso等。
圖片上傳:一般要支援斷點續傳。
7.3.3網路快取
適當快取,可讓App看起來更快。
使用DiskLruCache。
7.3.4打包網路請求
網路狀況好(如:WiFi狀態下),可一次非同步發起多個業務模組的資料請求。
7.3.5監聽相關狀態變化
休眠狀態(即:熄屏狀態下),儘量不要發起網路請求。
充電狀態,可適當做一些必要的網路請求,但要控制頻率。
弱網狀態下,可壓縮和減少資料傳輸量;不要自動載入圖片,用佔點陣圖顯示;頁面檢視先顯示,網路請求延遲提交。
7.3.6優化網路請求機制
劃分網路請求的優先順序,同一頁面,同一模組,重要的資料優先請求。
網路差,減少請求量;網路好,提高請求量。
合併網路請求,減少請求次數。比如,本地埋點資料,無需實時上報,可先本地快取,再根據上報策略,選擇合適時機一併上報。
7.3.8IP直連和HttpDns
IP直連,省去DNS解析時間。
使用HttpDns,防止運營商域名劫持或跨網訪問問題。
7.3.9優化請求頻率
使用本地快取,讓App在離線狀態也能使用。
優先使用快取;當沒有快取或快取國旗,再請求網路資料。
App效能優化,是一個持續地過程,需要我們不斷提高自己效能優化的能力,才能提高App的效能,才能打造出"快,省,穩"的極佳體驗App。
加油~~
大家有好的建議和看法,都歡迎在評論區留言,一起交流學習,謝謝?。