android app性能優化大匯總


  這里根據網絡上各位大神已經總結的知識內容做一個大匯總,作為記錄,方便后續“溫故知新”。

性能指標:

(1)使用流暢度:

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

(2)內存使用情況: 

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

(3)電量使用情況:

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

(4)流量使用情況:

  目前的網絡類型包含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盡量避免使用枚舉類型:

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

3、避免創建不必要的對象:(特別是在onDraw類似的函數里)

創建太多的對象會造成性能低下,這誰都知道,可是為什么呢?首先分配內存本身需要時間,其次虛擬機運行時堆內存使用量是有上限的,當使用量到達一定程度時會觸發垃圾回收,垃圾回收會使得線程甚至是整個進程暫停運行。可想而知,如果有對象頻繁的創建和銷毀,或者內存使用率很高,就會造成應用程序嚴重卡頓。(內存抖動)

4、合理使用static成員:

主要有三點需要掌握:
(1)如果一個方法不需要操作運行時的動態變量和方法,那么可以將方法設置為static的。
(2)常量字段要聲明為“static final”,因為這樣常量會被存放在dex文件的靜態字段初始化器中被直接訪問,否則在運行時需要通過編譯時自動生成的一些函數來初始化。此規則只對基本類型和String類型有效。
(3)不要將視圖控件聲明為static,因為View對象會引用Activity對象,當Activity退出時其對象本身無法被銷毀,會造成內存溢出。

5、 使用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條

6、避免使用浮點類型:

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

7、了解並使用庫函數:

Java標准庫和Android Framework中包含了大量高效且健壯的庫函數,很多函數還采用了native實現,通常情況下比我們用Java實現同樣功能的代碼的效率要高很多。所以善於使用系統庫函數可以節省開發時間,並且也不容易出錯。

 8、避免依賴注入框架:

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

9、小心使用外部依賴包:

很多依賴包都不是專門為了移動環境或者移動客戶端寫的。如果你決定使用一個外部依賴包,你應該提前明白你需要為了將它移植到移動端而消耗花費大量的時間和工作量。請在使用外部依賴包得時候提前分析他的代碼和內存占用

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

請注意不要落入一個依賴包的陷阱,你不希望引入一大片你根本不會使用到的代碼。如果你無法找到一種已經實現的邏輯來完全滿足你的需求,那么你盡量創建一個自己的實現方式。

10、避免內部的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.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM