拿小車舉例,你們知道什麼是一輛小車的性能嗎?同窗甲說,是否省油、加速是否夠快、開起來是否穩定、安全等等。web
沒錯,那就是小車的性能。數據庫
那App的性能又是指什麼呢?同窗乙說,App啓動是否夠快,運行是否流暢,是否省電、省流量,安裝包體積是否夠小等等。json
是的,這就是App的性能。緩存
咱們知道,一輛小車性能越好,加速越快,跑的越穩,越省油。安全
App也同樣,性能越好,運行更流暢、更穩定、更省流量、電量,包的體積也會更小,這能給用戶帶來優秀的體驗,進而也會提高App的知名度。性能優化
既然App性能那麼重要,那咱們就要掌握App性能優化的技能了。服務器
掌握App性能優化,是Android開發人員進階中高級的必備技能。那如何進行App的性能優化呢?網絡
咱們能夠從這幾個方面入手:卡頓優化、內存優化、穩定性優化、耗電優化、安裝包大小優化、數據庫SQLite優化、網絡優化。數據結構
接下來,咱們逐一展開講解。框架
可分爲四個大的方向:
UI包括繪製和渲染。
啓動可分爲冷啓動、熱啓動。
跳轉包括頁面間跳轉和先後臺切換。
包括:點擊、滑動、系統事件、按鍵。
可分爲如下兩方面緣由:
首先,咱們要明白這樣一個概念,人類肉眼在看每秒60幀(即:每幀16ms)的畫面時,是不會感覺畫面卡頓,當低於60幀/秒,咱們就會感覺到畫面卡頓了。
Android系統每隔16ms就發出Vsync,觸發對UI的渲染。若是每次都在<=16ms內完成渲染,界面就會流暢;若是每次都在>16ms才能完成渲染,就會形成丟幀,界面就會卡頓。
主要包括數據處理耗時,數據處理佔用CPU太高,內存增長致使頻繁GC等。
Hierarchy View,Profile GPU Rendering,TraceView,Systrace
減小布局層級嵌套,佈局複用,刪除無用屬性,使用ViewStub提升顯示速度。
經常使用佈局的優化,自定義View的優化。
UI佈局,邏輯加載優化,數據準備策略優化。
減小刷新次數,縮小刷新區域,避免後臺有較高的CPU線程運行。
其餘:好比,使用動畫效果,根據不一樣場景選擇合適的動畫框架實現。有些狀況,可使用硬件加速來提升流暢度。
Android應用都是在Android虛擬機上運行的,內存分配和垃圾回收都是由Android虛擬機來完成的。
建立-使用-銷燬(包括:不可見-不可達-收集-終結-對象再分配)。
Android系統內存分配,其實是對堆的分配和釋放。
年輕代、老年代、持久代。
全部新生成的對象都放在年輕代。
年輕代分爲一個Eden區和兩個Survivor區。
GC時,當Eden區滿時,還存活的對象會被複制到其中一個Survivor區(A)。
當這個Survivor區(A)也滿時,就會被複制到另外一個Survivor區(B)。
當Survivor區(B)也滿時,從第一個Survivor(B)複製過來而且還存活的對象,就會被複制到老年代。
在年輕代經歷了N次垃圾回收仍然存活的到對象,就被放到老年代。
主要存放靜態文件,好比Java類,方法等。
持久代對垃圾回收沒有明顯影響。
若是持久代空間過小,可經過-XX:MaxPermSize =< N配置。
資源類的對象未關閉。
註冊系統事件未註銷:使用Sensor Manager等系統服務,Context.getSystemService(int name)獲取系統服務。
類的靜態變量持有大數據對象:如,activity的靜態變量持有該activty的引用。
非靜態內部類的靜態實例。
Handler形成內存泄漏。
WebView。
匿名類:new AsyncTask,new Thead,TimerTask。這些匿名類對象結束以前一直持有對應activity的引用,致使activity實例沒法被回收,形成內存泄漏。
Memory Monitor,Heap Viewer,Allocation Tracker,Memory Analyzer Tool,LeakCanary。
根據實際需求,合理使用強引用,軟引用,弱引用,虛引用。
增長內存複用:好比合理使用系統自帶的資源,視圖,圖片,對象池等的複用。
留意自動裝箱。
使用最優數據類型,好比使用ArrayMap,避免使用枚舉類型,使用LruCache等。
圖片壓縮,圖片緩存。
Crash,ANR。
穩定性主要依賴代碼優化,邏輯實現的優化來提高。因此從代碼層面來看,分析工具主要有:Android Lint,Findbugs,Checkstyle,PMD,FireLine。
App耗電嚴重,會給用戶帶來很是差的體驗,致使用戶卸載應用。
這是Google出的Android系統電量分析工具。
避免浮點運算等等。
節省流量,提升用戶對App的好感度。
使用ProGuard工具進行壓縮,優化,混淆。ProGuard的原理:壓縮,優化,混淆。
使用Android Lint刪除冗餘資源,使資源文件最小化。
使用AAPT,TinyPng壓縮圖片,使用webP圖片格式等。
對比選擇最優庫,不要引入多個相似功能的庫。若是有相關庫的源碼,可根據實際需求,抽取須要的代碼從新編譯庫,讓庫儘量的小。
可將功能模塊放服務器,須要用時再加載。
文章APK極限壓縮:
索引是對數據庫表中一列或多列數據進行排序的一種數據結構。可理解爲一個指向表中數據的指針,與一本書的目錄相似。
加快表中數據查詢速度。
建立索引自己也會形成資源開銷。
表索引: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)。
合理使用索引,可加快數據庫表數據的查詢速率。
對數據庫原子性的操做。
爲數據的總體性執行帶來可靠安全性,爲更新和刪除操做帶來很大優化。
保證數據的完整性,安全性,提升數據更新,刪除操做的效率。
儘可能少用cursor.getColumnIndex()。
用StringBuilder(非線程安全)或StringBuffer(線程安全)來拼接字符串。
查詢時,只返回須要的數據或結果。
cursor使用後要及時關閉。
網絡優化很差,形成用戶流量消耗大,耗電快,用戶等待時間長體驗差等。
Network Monitor,Charles,Fiddler,Stecho。
API設計要合理。
使用GZIP壓縮。
選擇合適的數據格式:json,xml,protocol Buffer。
圖片下載:
使用縮略圖。
使用WebP圖片。
根據設備規格,指定圖片尺寸請求圖片。
使用完善的合適的圖片加載框架:Glide,Picasso等。
圖片上傳:通常要支持斷點續傳。
適當緩存,可以讓App看起來更快。
使用DiskLruCache。
網絡情況好(如:WiFi狀態下),可一次異步發起多個業務模塊的數據請求。
休眠狀態(即:熄屏狀態下),儘可能不要發起網絡請求。
充電狀態,可適當作一些必要的網絡請求,但要控制頻率。
弱網狀態下,可壓縮和減小數據傳輸量;不要自動加載圖片,用佔位圖顯示;頁面視圖先顯示,網絡請求延遲提交。
劃分網絡請求的優先級,同一頁面,同一模塊,重要的數據優先請求。
網絡差,減小請求量;網絡好,提升請求量。
合併網絡請求,減小請求次數。好比,本地埋點數據,無需實時上報,可先本地緩存,再根據上報策略,選擇合適時機一併上報。
IP直連,省去DNS解析時間。
使用HttpDns,防止運營商域名劫持或跨網訪問問題。
使用本地緩存,讓App在離線狀態也能使用。
優先使用緩存;當沒有緩存或緩存國旗,再請求網絡數據。
App性能優化,是一個持續地過程,須要咱們不斷提升本身性能優化的能力,才能提升App的性能,才能打造出"快,省,穩"的極佳體驗App。
加油~~
你們有好的建議和見解,都歡迎在評論區留言,一塊兒交流學習,謝謝🙏。