Android下常見的記憶體泄露 經典

來源:互聯網
上載者:User

標籤:android   des   style   class   java   tar   

轉自:http://www.linuxidc.com/Linux/2011-10/44785.htm

因為Android使用Java作為開發語言,很多人在使用會不注意記憶體的問題。

於是有時遇到程式運行時不斷消耗記憶體,最終導致OutOfMemery,程式異常退出,這就是記憶體泄露導致的。

我們現在就來總結一下可能導致記憶體泄露的情況:

    1. 查詢資料庫而沒有關閉Cursor

      在Android中,Cursor是很常用的一個對象,但在寫代碼是,經常會有人忘記調用close, 或者因為代碼邏輯問題狀況導致close未被調用。

       

      通常,在Activity中,我們可以調用startManagingCursor或直接使用managedQuery讓Activity自動管理Cursor對象。
      但需要注意的是,當Activity介紹後,Cursor將不再可用!
      若操作Cursor的代碼和UI不同步(如後台線程),那沒需要先判斷Activity是否已經結束,或者在調用OnDestroy前,先等待後台線程結束。

      除此之外,以下也是比較常見的Cursor不會被關閉的情況:

       

      1. try {  
      2.     Cursor c = queryCursor();  
      3.     int a = c.getInt(1);  
      4.     ......  
      5.     c.close();  
      6. catch (Exception e) {  
      7. }  
      雖然表面看起來,Cursor.close()已經被調用,但若出現異常,將會跳過close(),從而導致記憶體泄露。

      所以,我們的代碼應該以如下的方式編寫:

      1. Cursor c = queryCursor();  
      2. try {      
      3.     int a = c.getInt(1);  
      4.     ......  
      5. catch (Exception e) {  
      6. finally {  
      7.     c.close(); //在finally中調用close(), 保證其一定會被調用   
      8. }  

       

    2. 調用registerReceiver後未調用unregisterReceiver().

      在調用registerReceiver後,若未調用unregisterReceiver,其所佔的記憶體是相當大的。
      而我們經常可以看到類似於如下的代碼:

      1. registerReceiver(new BroadcastReceiver() {  
      2.     ...  
      3. }, filter); ...  
      這是個很嚴重的錯誤,因為它會導致BroadcastReceiver不會被unregister而導致記憶體泄露。

       

    3. 未關閉InputStream/OutputStream

      在使用檔案或者訪問網路資源時,使用了InputStream/OutputStream也會導致記憶體泄露

    4. Bitmap使用後未調用recycle()

      根據SDK的描述,調用recycle並不是必須的。但在實際使用時,Bitmap佔用的記憶體是很大的,所以當我們不再使用時,盡量調用recycle()以釋放資源。

       

    5. Context泄露

       

      這是一個很隱晦的記憶體泄露的情況。
      先讓我們看一下以下代碼:
      1. private static Drawable sBackground;  
      2.   
      3. @Override  
      4. protected void onCreate(Bundle state) {  
      5.   super.onCreate(state);  
      6.     
      7.   TextView label = new TextView(this);  
      8.   label.setText("Leaks are bad");  
      9.     
      10.   if (sBackground == null) {  
      11.     sBackground = getDrawable(R.drawable.large_bitmap);  
      12.   }  
      13.   label.setBackgroundDrawable(sBackground);  
      14.     
      15.   setContentView(label);  
      16. }  

      在這段代碼中,我們使用了一個static的Drawable對象。
      這通常發生在我們需要經常調用一個Drawable,而其載入又比較耗時,不希望每次載入Activity都去建立這個Drawable的情況。
      此時,使用static無疑是最快的代碼編寫方式,但是其也非常的糟糕。
      當一個Drawable被附加到View時,這個View會被設定為這個Drawable的callback (通過調用Drawable.setCallback()實現)。
      這就意味著,這個Drawable擁有一個TextView的引用,而TextView又擁有一個Activity的引用。
      這就會導致Activity在銷毀後,記憶體不會被釋放。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.