android開發中遇到的內存泄露(非大衆版)

http://www.cnblogs.com/leftwing/archive/2012/02/09/2343420.html

本來想早點睡覺的,這些天睡眠不足啊,弄這個內存泄露的問題壓力太大了,但是還是先記錄下來才能踏實 %><%

這幾天被師父派了個處理內存泄露的任務。先說說狀況,在eclipse中可以通過DDMS的heap來查看程序在內存中的佔用情況。而我要處理的這個程序,每次運行後退出,都會使得allocated項增加0.1M,這樣反覆運行幾百次之後,程序就會砰的一下,崩潰了---

 

於是就開始找問題。用到了一款工具——MAT,是用來分析內存問題的,這個網上一搜也一大堆,用法也一大堆,所以我就不多說了。以前沒用過這個,不知道是這個軟件自身功能的限制,還是我沒摸透他的功能,反正通過mat只是找出來了一點點很籠統的提示,最大的問題之一就是MessageQueue有問題,那我就在偌大的工程中去找Message啊、Handler之類的相關代碼吧。

 

一下子就花了三天的時間,因爲實在是不知道在哪會出現什麼樣的問題,最後是通過自己寫了幾個小程序,模擬了一下Handler的幾種用法,才發現的問題。正常用下來的話,handleMessage()基本上不會出什麼問題;平常的用一下postDelayed()也不會出什麼問題;但是postDelayed()嵌套就會有問題了。

先來個造成問題的代碼(灰常的簡單,只是爲了演示一下問題):

 1 package example.HandlerTest;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.os.Handler;
 6 
 7 public class HandlerTest extends Activity {
 8 
 9     Handler handler=new Handler();
10     
11     /** Called when the activity is first created. */
12     @Override
13     public void onCreate(Bundle savedInstanceState) {
14         super.onCreate(savedInstanceState);
15         setContentView(R.layout.main);
16         
17         handler.postDelayed(new Runnable() {
18             
19             @Override
20             public void run() {
21                 // TODO Auto-generated method stub
22                 System.out.println(this.toString());
23                 
24                 //這裏是問題的所在
25                 handler.postDelayed(this, 2000);
26             }
27         }, 2000);
28     }
29     
30 }

在postDelayed()裏面,重寫的run方法中又有一個postDelayed(),這樣就會造成程序返回或者activity關閉的時候,後臺仍然會有一個線程在跑,上個效果圖:

這是我運行兩次後的輸出結果,程序退出了,後臺仍然有兩個線程在跑,無法被釋放,如果是大程序,就會導致:一、耗電;二、內存泄露。

解決方法:

在程序銷燬的時候,要通過Handler的removeCallbacks(Runnable r)方法來手動釋放掉該線程,當然要把Runnable單獨提出來寫,再來個修改後的代碼:

 1 package example.HandlerTest;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.os.Handler;
 6 import android.view.KeyEvent;
 7 
 8 public class HandlerTest extends Activity {
 9 
10     Handler handler=new Handler();
11     
12     /** Called when the activity is first created. */
13     @Override
14     public void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.main);
17         
18         handler.postDelayed(handlerRunnable, 2000);
19     }
20 
21     @Override
22     protected void onDestroy() {
23         // TODO Auto-generated method stub
24         handler.removeCallbacks(handlerRunnable);
25         super.onDestroy();
26     }
27 
28 
29 
30     Runnable handlerRunnable=new Runnable() {
31         
32         @Override
33         public void run() {
34             // TODO Auto-generated method stub
35             System.out.println(this.toString());
36             
37             handler.postDelayed(this, 2000);
38         }
39     };
40 }

就不上效果圖了。調用removeCallbacks()的時機是在一個activity退出的時候,一個類銷燬的時候,這種情況都可以用onDestroy方法;再有就是可以在一個activity返回的時候,重寫一下onKeyDown()方法,在裏面remove。

以上就是我想記錄下來的問題,還有一點,有個帖子提到了創建Message對象不能用new,而是要用Message.obtain()來創建,否則也會造成內存泄露。這一點我沒驗證過,不過官方的創建方法的確是obtain,沒有用new的,這裏也記錄一下吧。

本人菜鳥,文筆和技術都還不過關,請多多指教~~~~~~~~ ^_^


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章