android app性能優化大彙總

  這裏根據網絡上各位大神已經總結的知識內容作一個大彙總,做爲記錄,方便後續「溫故知新」。html

性能指標:

(1)使用流暢度:android

   圖片處理器每秒刷新的幀數(FPS),可用來指示頁面是否平滑的渲染。高的幀率能夠獲得更流暢,更逼真的動畫,不過幀率達到60fps以上,人眼主觀感覺到的差異就不大了。因此以60fps做爲衡量標準,即要求每一幀刷新的時間小於16ms,這樣才能保證滑動中平滑的流暢度。編程

(2)內存使用狀況: 數組

  在android系統中,每一個APP進程除了同其餘進程共享(shared dirty)外,還獨用私有內存(private dirty),一般咱們使用PSS(=私有內存+比例分配共享內存)來衡量一個APP的內存開銷。移動設備的內存資源是很是有限,爲每一個APP進程分配的私有內存也是有限制。一方面咱們要合理的申請內存使用,以避免致使頻繁的GC影響性能和大對象申請發生內存溢出;另外一方面,咱們要及時釋放內存,以避免發生內存泄漏。緩存

(3)電量使用狀況:性能優化

  相對於PC來講,移動設備的電池電量是很是有限的,保持持久的續航能力尤其重要。另外,android的不少特性都比較耗電(如屏幕,GPS,sensor傳感器,喚醒機制,CPU,連網等的使用),咱們必需要慎重檢查APP的電量使用,以避免致使用戶手機耗電發熱,帶來不良體驗。網絡

(4)流量使用狀況:app

  目前的網絡類型包含2G\3G\4G\wifi,其中還有不一樣運營商的區分,咱們在APP的使用中常常遇到大資源,重複請求,調用響應慢,調用失敗等各類狀況。在不一樣的網絡類型之下,咱們不只要控制流量使用,還須要加快請求的響應。框架

原理以及優化技術要點

原理及相關知識介紹請參考google官方的教程:函數

android app性能優化大彙總(google官方Android性能優化典範 - 第1季)

android app性能優化大彙總(google官方Android性能優化典範 - 第2季)

android app性能優化大彙總(google官方Android性能優化典範 - 第3季)

具體優化方案:

android app性能優化大彙總(UI渲染性能優化)

android app性能優化大彙總(內存性能優化)

 

 代碼編寫風格細節對性能的影響:

1使用優化後的數據容器:

請使用 Andorid 框架中優化過的數據容器,例如 SparseArray,SparseBooleanArray 和 LongSparseArray。相似於 HashMap 這一類的容器的效率不是很高,由於在每一個 Map 中對於每一次的存放數據,他都須要獨立一個單獨的 Entry 對象進行傳芳。而 SparseArray 因爲禁止系統自動封裝鍵值對,所以他更加有效率。而且你不須要擔憂丟失掉原有信息。

2儘可能避免使用枚舉類型:

枚舉與靜態常量相比,一般會消耗兩倍的內存資源。

三、避免建立沒必要要的對象:(特別是在onDraw相似的函數裏)

建立太多的對象會形成性能低下,這誰都知道,但是爲何呢?首先分配內存自己須要時間,其次虛擬機運行時堆內存使用量是有上限的,當使用量到達必定程度時會觸發垃圾回收,垃圾回收會使得線程甚至是整個進程暫停運行。可想而知,若是有對象頻繁的建立和銷燬,或者內存使用率很高,就會形成應用程序嚴重卡頓。(內存抖動)

四、合理使用static成員:

主要有三點須要掌握:
(1)若是一個方法不須要操做運行時的動態變量和方法,那麼能夠將方法設置爲static的。
(2)常量字段要聲明爲「static final」,由於這樣常量會被存放在dex文件的靜態字段初始化器中被直接訪問,不然在運行時須要經過編譯時自動生成的一些函數來初始化。此規則只對基本類型和String類型有效。
(3)不要將視圖控件聲明爲static,由於View對象會引用Activity對象,當Activity退出時其對象自己沒法被銷燬,會形成內存溢出。

五、 使用for-each循環:

加強的For循環(也被稱爲 for-each 循環)能夠被用在實現了 Iterable 接口的 collections 以及數組上。使用collection的時候,Iterator (迭代器,譯者注) 會被分配,用於for-each調用 hasNext() 和 next() 方法。使用ArrayList時,手寫的計數式for循環會快3倍(無論有沒有JIT),可是對於其餘collection,加強的for-each循環寫法會和迭代器寫法的效率同樣。

請比較下面三種循環的方法:

static class Foo {  
int mSplat;
}
Foo[] mArray = ...
public void zero() {  
  int sum = 0;  
  for (int i = 0; i < mArray.length; ++i) {
    sum += mArray[i].mSplat;  
  }
}
  
public void one() {  
  int sum = 0;  
  Foo[] localArray = mArray;  
  int len = localArray.length;  
  for (int i = 0; i < len; ++i) {
    sum += localArray[i].mSplat;  
  }
}

public void two() {  
  int sum = 0;  
  for (Foo a : mArray) {
      sum += a.mSplat;
  }
}
  • zero()是最慢的,由於JIT沒有辦法對它進行優化。

  • one()稍微快些。

  • two() 在沒有作JIT時是最快的,但是若是通過JIT以後,與方法one()是差很少同樣快的。它使用了加強的循環方法for-each。

因此請儘可能使用for-each的方法,可是對於ArrayList,請使用方法one()。

你還能夠參考 Josh Bloch 的 《Effective Java》這本書的第46條

六、避免使用浮點類型:

經驗之談,所在Android設備中浮點型大概比整型數據處理速度慢兩倍,以若是整型能夠解決的問題就不要用浮點型。另外,一些處理器有硬件乘法可是沒有除法,這種狀況下除法和取模運算是用軟件實現的。爲了提升效率,在寫運算式時能夠考慮將一些除法操做直接改寫爲乘法實現,例如將「x / 2」改寫爲「x * 0.5」。

七、瞭解並使用庫函數:

Java標準庫和Android Framework中包含了大量高效且健壯的庫函數,不少函數還採用了native實現,一般狀況下比咱們用Java實現一樣功能的代碼的效率要高不少。因此善於使用系統庫函數能夠節省開發時間,而且也不容易出錯。

 八、避免依賴注入框架:

使用相似於 Guice 和 RoboGuice 的依賴注射框架,或許會使你的代碼變得更加漂亮,由於他們可以減小你須要寫的代碼,而且爲測試或者在其餘條件改變的狀況下,提供一種自適應的環境。可是,這些框架在初始化的時候會由於註釋而消耗大量的工做在掃描你的代碼上,這會讓你的代碼在進行內存映射的時候花費更多的資源。雖然這些內存可以被 Android 進行回收,可是等待整個分頁被釋放須要很長一段時間。

九、當心使用外部依賴包:

不少依賴包都不是專門爲了移動環境或者移動客戶端寫的。若是你決定使用一個外部依賴包,你應該提早明白你須要爲了將它移植到移動端而消耗花費大量的時間和工做量。請在使用外部依賴包得時候提早分析他的代碼和內存佔用

即便依賴包是爲了 Android 而設計的,可是這也有潛伏的危險,由於每個包都作着不一樣的工做。例如,有一個依賴包使用納米級的 protobufs 可是別的包使用微米級的 protobufs.那麼如今在你的應用中就有兩套 protobuf 的標準了。這會在你記錄數據,分析數據,加載圖像,緩存,或者其餘任何可能的狀況下發生你不但願發生的事情。ProGuard 沒法在這裏幫助你,由於他們都是你所依賴包的底層實現,。當你使用從別的依賴包(他可能繼承了不少的依賴包)裏繼承的 Activity 時,這個問題變得尤爲嚴重,當你使用反射以及幹別的事情的時候

請注意不要落入一個依賴包的陷阱,你不但願引入一大片你根本不會使用到的代碼。若是你沒法找到一種已經實現的邏輯來徹底知足你的需求,那麼你儘可能建立一個本身的實現方式。

十、避免內部的Getters/Setters:

像C++等native language,一般使用getters(i = getCount())而不是直接訪問變量(i =mCount)。這是編寫C++的一種優秀習慣,並且一般也被其餘面向對象的語言所採用,例如C#與Java,由於編譯器一般會作inline訪問,並且 你須要限制或者調試變量,你能夠在任什麼時候候在getter/setter裏面添加代碼。然而,在Android上,這是一個糟糕的寫法。虛函數的調用比起直接訪問變量要耗費更多。在面向對象編程中,將getter和setting暴露給公用接口是合理的,但在類內部應該僅僅使用域直接訪問。在沒有JIT(Just In Time Compiler)時,直接訪問變量的速度是調用getter的3倍。有JIT時,直接訪問變量的速度是經過getter訪問的7倍。請注意,若是你使用 ProGuard , 你能夠得到一樣的效果,由於ProGuard能夠爲你inline accessors.

相關文章
相關標籤/搜索