1. 程式人生 > >安卓開發之效能優化

安卓開發之效能優化

1. 避免建立不必要的物件
建立太多的物件會造成效能低下,首先分配記憶體本身需要時間,其次虛擬機器執行時堆記憶體使用量是有上限的,

google原生OS的預設值是16M,但是各個廠家的OS會對這個值進行修改。比如本人小米2S為例,這個值應該是96M。

當使用量到達一定程度時會觸發垃圾回收,垃圾回收會使得執行緒甚至是整個程序暫停執行。可想而知,如果有物件頻繁的建立和銷燬,或者記憶體使用率很高,就會造成應用程式嚴重卡頓。 

2.合理使用static成員
主要有三點需要掌握: 

不要將檢視控制元件宣告為static,因為View物件會引用Activity物件,當Activity退出時其物件本身無法被銷燬,會造成記憶體溢位。 

靜態引用的物件不會被垃圾回收

只要靜態變數沒有被銷燬也沒有置null,其物件一直被保持引用,也即引用計數不可能是0,因此不會被垃圾回收。因此,單例物件在執行時不會被回收。

3. 避免內部的Getters/Setters

面向物件設計中,欄位訪問使用Getters/Setters通常是一個好的原則,但是在Android開發中限於硬體條件,除非欄位需要被公開訪問,否則如果只是有限範圍內的內部訪問(例如包內訪問)則不建議使用Getters/Setters。在開啟JIT時,直接訪問的速度比間接訪問要快7倍。 

4. 使用增強for迴圈

優先使用增強for迴圈通常情況下會獲得更高的效率;除了一種情況,即對ArrayList進行遍歷時,使用普通的for迴圈效率要更高。 

5.佈局優化:

採用<merge>優化佈局層數。 採用<include>來共享佈局。

6.移除Activity預設背景,提升activity載入速度。

   如果確信在Activity中使用不透明的背景,那麼可以移除Activity的預設背景。 
在程式碼中:getWindow().setBackgroundDrawable(null); 
也可以在styles樣式檔案中設定並在Manifest檔案中配置

 <style name="MyStyle" parent="AppTheme">
        <item name="android:windowNoTitle"
>true</item> <item name="android:windowBackground">@null</item> </style>

7.廣播BroadCast動態註冊時,記得要在呼叫者生命週期結束時unregisterReceiver,防止記憶體洩漏。

8.合理使用StringBuffer,StringBuilder,String
在簡單的字串拼接中,String的效率是最高的,例如String s = “hello” + “world”; 
但大家這裡要注意的是,如果你的字串是來自另外的String物件的話,速度就沒那麼快了,例如: 
    String str2 = “This is”; 
    String str3 = “ a ”; 
    String str4 = “ test”; 
    String str1 = str2 +str3 + str4; 
這裡就要求使用StringBuilder了 

在單執行緒中,StringBuilder的效能要比StringBuffer高。多執行緒為了執行緒安全需要採用StringBuffer,因為它是同步的。常規下一般用StringBuilder。 

9.儘量使用區域性變數

呼叫方法時傳遞的引數以及在呼叫中建立的臨時變數都儲存在棧(Stack)中,速度較快。其他變數,如靜態變數、例項變數等,都在堆(Heap)中建立,速度較慢。另外,依賴於具體的編譯器/JVM,區域性變數還可能得到進一步優化。 

簡單說一下棧和堆的區別:

棧是一種具有後進先出性質的資料結構,也就是說後存放的先取,先存放的後取。這就如同我們要取出放在箱子裡面底下的東西(放入的比較早的物體),我們首先要移開壓在它上面的物體(放入的比較晚的物體)。而堆就不同了,堆是一種經過排序的樹形資料結構,每個結點都有一個值。通常我們所說的堆的資料結構,是指二叉堆。堆的特點是根結點的值最小(或最大),且根結點的兩個子樹也是一個堆。由於堆的這個特性,常用來實現優先佇列,堆的存取是隨意,這就如同我們在圖書館的書架上取書,雖然書的擺放是有順序的,但是我們想取任意一本時不必像棧一樣,先取出前面所有的書,書架這種機制不同於箱子,我們可以直接取出我們想要的書。

10.I/O流操作記得及時關閉流物件。

11.使用Application Context代替Activity中的Context
不要讓生命週期長的物件引用activity context,即保證引用activity的物件要與activity本身生命週期是一樣的 
對於生命週期長的物件,可以使用Application Context 

不要把Context物件設定為靜態。 

12.集合中的物件要及時清理
 我們通常把一些物件的引用加入到了集合中,當我們不需要該物件時,並沒有把它的引用從集合中清理掉,這樣這個集合就會越來越大。如果這個集合是static的話,那情況就更嚴重了。 
13.Bitmap的使用
較大的Bitmap注意壓縮後再使用,載入高清大圖可以考慮BitmapRegionDecoder的使用, 

不再使用的Bitmap注意及時recycle().

14.儘量不要使用整張的大圖作為資原始檔,儘量使用9path圖片

應用圖示優先放在mipmap目錄下(AndroidStudio環境),其他資源圖,.9圖應該放在drawable-xxxx下,需要複製到手機sd卡上使用的應放在asset目錄 

15.關於WebView 

在Activity或者Fragment銷燬時記得把WebView也銷燬

@Override
    protected void onDestroy() {
        if (webView!= null) {
            webView.destroy();
            webView= null;
        }
        super.onDestroy();
    }
16.UI效能優化總結
  • 佈局優化;儘量使用include、merge、ViewStub標籤,儘量不存在冗餘巢狀及過於複雜佈局,儘量使用GONE替換INVISIBLE,使用weight後儘量將width和heigh設定為0dp減少運算,Item存在非常複雜的巢狀時考慮使用自定義View來取代,減少measure與layout次數等。

  • 列表及Adapter優化;儘量複用getView方法中的相關View,不重複獲取例項導致卡頓,列表儘量在滑動過程中不進行UI元素重新整理等。

  • 背景和圖片等記憶體分配優化;儘量減少不必要的背景設定,圖片儘量壓縮處理顯示,儘量避免頻繁記憶體抖動等問題出現。

  • 自定義View等繪圖與佈局優化;儘量避免在draw、measure、layout中做過於耗時及耗記憶體操作,尤其是draw方法中,儘量減少draw、measure、layout等執行次數。

  • 避免ANR,不要在UI執行緒中做耗時操作,遵守ANR規避守則,譬如多次操作資料庫操作等。