Android應用優化小手冊

對我們技術從業者而言,很多時候時候不是我們不知道怎麼做,而是不知道做什麼?今天系統的總結自己關於如何對Android應用進行優化的一些經驗,共計八個維度.

這裏寫圖片描述


1.佈局優化

爲什麼?

Android系統每個16ms發出VSYNC信號,觸發對UI的渲染,要想達到界面流暢,必須實現60fps,也就意味着大多數的操作必須在16ms完成.

除了上面界面過於複雜導致渲染不能及時完成之外,還存在過度繪製問題.所謂過度繪製就是某個像素在同一幀的時間內被繪製多次.在多層次的UI界面中,如果不可見的UI也在進行繪製,那麼這些重合區域的像素就會被繪製多次,從而浪費大量的CPU和GPU資源.過度繪製也發生在背景重疊的情況下,比如Layout中有自己的背景,同時子View中又有自己的背景.

如何檢測?

  • 使用HierarchyViewer來查找Activity中的佈局是否過於複雜
  • 在開發者選項中打開Show GPU Overdraw選項進行觀察是否存在過度繪製
  • 在開發者選項中選擇Profile GPU Rendering,選中On screen as bar
  • 使用TraceView來觀察CPU執行情況

如何優化?

  • 減少佈局的層級,合理的使用include,merge,ViewStub
  • 自定義組件的onDraw()中避免大量創建臨時對象,比如String,以免頻繁觸發GC
  • 自定義組件的onDraw()中,考慮使用canvas.clipRect()繪製需要被繪製的區域
  • 對像ListView這樣的組件容器,考慮使用convertView,使用ViewHolder,
  • 考慮使用性能更高的組件,比如推薦使用RecycleView來代替ListView,使用staticlayout來實現自動換行

2.內存優化

爲什麼?

資源總是有限的,內存同樣也是一種資源.在Android當中,過度的/不恰當佔用內存資源,會導致應用頻繁被殺死,最終也會影響用戶的整體體驗.任何一名開發者,都應該將節省內存牢記心中.

如何檢測?

  • 使用LeakCanary
  • 使用MAT分析Java堆
  • 使用Android Device Monitor中的Application Tracker追蹤內存分配信息
  • Android Studio中的Android Monitor,選擇其中的Memory

如何優化?

  • 主動的釋放內存,在onLowMemory()和onTrimMemory()中適當的釋放內存

  • 避免內存泄漏和內存溢出

  • 在使用Bitmap的時候,考慮對其進行壓縮,使用緩存或者改變顏色模式,比如android默認的顏色格式是ARGB_8888,在要求不高的情況下可以採用RGB__565,這樣每個像素1佔用的內存就可懂4byte到2byte.

  • 減少幀動畫的使用,如果需要,通過SurfaceView實現

  • 使用更輕量級的數據結構,比如ArrayMap/SparseArray

  • 合理的使用相關組件,比如Service和Webview,在不需要的時候主動結束其生命週期

  • 合理的使用多進程,比如像音樂播放器類,可以分爲主進程和播放進程

  • 使用異步隊列時考慮有界隊列

  • 如果你能明確知道HashMap的大小,那就再初始化時爲其制定容量


3.電量優化

爲什麼?

電量是移動設備非常寶貴的資源,作爲一名開發者,有必要爲用戶着想,減少電量的消耗.調查顯示通常只有30%左右的電量是被程序核心的功能所消耗,比如界面渲染,剩下的70%則是被上報數據,位置更新,後臺通知所消耗.

如何檢測?

  • 手機選項中通過查看APP的電量消耗的統計數據
  • 使用Battery Historian Tool來查看詳細的電量消耗

如何優化?

  • 減少喚醒屏幕的次數與持續的時間,正確的使用WakeLock.
  • 延遲非必須的操作到充電狀態時,比如日誌上報完全可以在夜間充電時完成,這點可以結合JobScheduler使用
  • 使用傳感器採集數據時,一旦不需要記得取消註冊.
  • 減少網絡通信,合併通信.
  • 合理使用定位功能,減少位置更新頻率以及根據實際情況使用不同精度的定位需求

4.網絡優化

爲什麼?

現在App幾乎都需要聯網操作,做好網絡優化一方面可以提高體驗,另一方面可以減少流量和電量的損耗.另外,無論是對用戶還是網絡服務提供者,網絡同樣是一種資源,任何開發者都不應該假設網絡資源是無限制的.

如何檢測?

  • 使用Android Studio裏的Network Traffic Tools來查看網絡請求
  • 使用Android Studio中的Monitor
  • 使用Fidder或者Charles等抓包工具分析網絡數據包

如何優化?

  • 有必要的時候務必做好緩存,無論是圖片還是普通的數據,使用LruCache和DiskLruCache構建自己的緩存系統,並根據實際場景設計緩存策略
  • 避免過度的網絡同步,合併相關的網絡請求
  • 根據實際場景確定請求策略,避免使用固定的間隔頻率來進行網絡操作.比如連接WiFi並充電的情況下請求頻率可以高,第一次網絡請求失敗後可以使用雙倍的時間間隔來進行下一次
  • 減少數據傳輸量,對傳輸的數據做壓縮.如果傳輸的是圖片,需要選擇合適的圖片格式以及根據顯示大小請求合適規格的圖片.對於普通數據,可以考慮使用ProtocalBuffers來減小傳輸數據的大小.
  • 某些情況下可以採用IP直連,一方面可以減少DNS解析時間,另一方面可以防止域名劫持

5.啓動優化

爲什麼?

啓動優化看起來並不是那麼必要,但從心理學角度而言,越快的啓動速度往往給用戶以性能好,高效可靠的心理暗示,這就很容易讓用戶對其產生好感,爲你後面打動用戶留下了餘地.

如何檢測?

  • 使用Method Tracing
  • 使用Systrace,比如在onCreate中添加trace.beginSection()和trace.endSection()
  • 使用adb shell am start -W [packageName]/[packageName.MainActivity]測量冷啓動時間

如何優化?

  • Activity的onCreate()中減少複雜和耗時的操作
  • Application的onCreate(),attachBaseContext()中同樣減少複雜和耗時的操作,但是對於很多App在此處會執行大量組件和服務的初始化操作,如果可能考慮並行初始化
  • 提供自定義啓動窗口,比如將一張圖片通過設置主題的方式顯示爲啓動窗口.
  • 優化佈局

6.體積優化

爲什麼?

對用戶而言,無論是用戶空間還是網絡,亦或是時間,都是資源.體積優化就是爲用戶節省資源的重要一環.如果你現在做的是SDK類產品,那麼體積優化同樣重要.

如何檢測?

  • 使用Android Lint檢查沒有使用的資源

如何優化?

  • 減少不必要的依賴庫/Jar,在滿足需求的前提下優先選擇體積小的.
  • 使用Proguard工具進行代碼瘦身,優化,混淆
  • 減少so文件的數量,根據實際情況提供so文件
  • 使用Gradle中的shrinkResource來將無用的代碼和資源排除在APK安裝包之外
  • 減少圖片資源的大小,考慮圖片壓縮或者使用Vertor Drawable替代png/jpeg
  • 有選擇的提供對應分辨率的圖片資源
  • 複用已經存在的圖片,多用通過代碼對已有圖片進行變換的方式實現複用
  • 使用插件化技術(如果項目簡單就不要使用)

7.性能優化

能發揮出100%的能力就不要只發揮其中的50%,這對應用而言並非壞事.同樣的價格賣給用戶兩輛車,我想大多數人會選擇性能更好的.

如何檢測?

  • 使用Lint執行靜態分析,在Android Studio的Analysis->Inspect Code
  • 在開發者選項中開啓StrictMode或者在代碼中開啓
  • 代碼Review

如何優化?

  • 任務並行化,對可能的任務進行並行操作,多借助線程池而非直接使用線程
  • 如何需要序列化數據,優先考慮Android自身提供的而非Java提供的Serializable
  • 選擇合適的數據結構,明確List/Set/Map/Stack操作的複雜度
  • 使用Android提供更高效的容器,比如使用ArrayMap來代替HashMap,此外還是有SparseBoolMap,SparseIntMap,SparseLongMap
  • 使用靜態常量代替Enum類型,可以減少至少兩倍的內存消耗
  • 使用對象池技術,比如提供想String一樣的對象池
  • 使用緩存技術
  • 字符串拼接操作有限使用StringBuilder
  • 對相關的算法和邏輯進行優化,減少不必要的流程
  • 採用JNI,對計算量較大的邏輯將其協程so文件,如圖片處理

業務優化

除了上述比較通用的優化方案之外,也應該花點時間放在業務優化上.很多時候,迫於時間壓迫,當前實現業務的方案並非最優.比如爲了支持多張圖片上傳,很多人直接使用串行操作,儘管這樣做容易實現,但是卻並非最佳.

由於每個產品的業務並不相同,也就很難有通用的優化方案,這裏又兩個目標值得思考:

  • 如果有可能,串行業務並行化
  • 如果有可能,簡化業務流程.將一大象關進冰箱的方法就是打開冰箱,將大象放進去,最後關閉冰箱.

之所以把業務優化放在最後的根本原因是業務優化的風險較高,需要團隊的整體配合來完成.

該顏色模式下顏色細膩,顯示質量最高,佔用的內存也最大,


  1. Android中圖片有四種顏色格式,分別是 

    默認的是ARGB_8888,其中ARGB分別代表的是透明度,紅色,綠色,藍色,每個值分別用8位來記錄,也就是一個像素會佔用4byte,共32位. 
    ARGB_4444和以上很類似,但是每個值分別用4位來記錄,也就是一個像素會佔用2byte,共16位. 
    RGB_565則分別用5位,6位,5位來記錄每個值,不存在透明度,每個像素會佔用2byte,共16位. 
    ALPHA_8:該像素只保存透明度,會佔用1byte,共8位. 
    在實際應用中而言,值推薦使用ARGB_8888以及RGB_565,如果你不需要透明度,那麼就選擇RGB_565,可以減少一半的內存佔用. 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章