1. 程式人生 > >Android中記憶體洩漏的幾種情況

Android中記憶體洩漏的幾種情況

1.單例造成的記憶體洩漏;

Android中單例模式中的餓漢式寫法如下:

public class Example 

{

private static Example Instance;

private Example(Context context)

{

this.context = context;

}

public static Example getInstance(Context context)

{

if(instance == null)

{

synchroized(Example.class)

{

if(instance == null)

{

instance = new Example(context);

}

}

}

return instance;

}

}

或者我們平時最常用到的單例模式

public class Example 

{

private static Example Instance;

private Example(Context context)

{

this.context = context;

}

public static Example getInstance(Context context)

{

if(instance == null)

{

instance = new Example(context);

}

return instance;

}

}

我們在activity中呼叫getInstance()並傳入this時,Example中便持有activity的引用,當activity退出時,activity無法會回收,就會造成記憶體洩漏.

正確的寫法是在Example的構造方法中做出如下修改:

private Example(Context context)

{

this.context = context.getapplicationcontext;

}

這樣修改以後,通過context獲取到Application的context,當activity銷燬時,activity便能被正常回收,不會造成記憶體洩漏,而Application的生命週期與Example類是一致的.

2.外部類中持有非靜態內部類的靜態物件

看下面一段程式碼:

public class Mainactivity extend fragmentactivity

{

private static Example instance;

protected void onCreate(Bundle bundle)

{

super.onCreate(bundle);

setContentView(R.layout.activityman);

instance = new Example();

}

public class Example

{

}

}

mainactivity中建立了Example的靜態物件,從而Example持有了activity的引用,在activity銷燬時無法被回收,從而造成記憶體洩漏,解決的方法是instance修改為非靜態物件,,或者把Example修改為靜態內部累,從未避免造成記憶體洩漏.

3.Handle和Runnable作為非靜態內部類

我們在使用Handler或new Runnable時,通常使用匿名內部類的形式,即直接new出一個物件進行一些延時操作,如果在延時等待過程中,activity被銷燬了,此時acitivity無法被銷燬並回收,會造成記憶體洩漏.在寫程式碼時,應該將Handler或Runnable定義為靜態內部類,然後在activity中new出這些類的物件,再進行延時操作.

然後最好在onDestory()中呼叫handler.removecallbacks(runnable)取消定時操作,這樣在acitivity銷燬後, 也不會觸發run()方法.

Note:還有一種比較少見的情況,就是在Handler或Runnable的構造方法中需要Context物件,在activity中呼叫Handler或Runnable類建立物件並傳入this時,Handler或Runnable也會持有acitivity的引用,同樣會造成記憶體洩漏.修改方法是使用若引用傳入context,程式碼如下:

private class Mainactivity extend FragmentActivity{

private MyHandler mHandler = new Handler(new  WeakPreference<Context>(this));

public statci class MyHandler exend Handle

{

private Context context;

public MyHandler(WeakPreference<Context> weakPreference)

{

context =weakPreference.get().

}

}

}

4.還有一些其他的違規操作會造成記憶體洩漏,如BroadcastReceiver,inputstream,cource使用後未及時unregisterReceiver或關閉,都會造成記憶體洩漏.

造成記憶體洩漏的主要原因是長生命週期持有短生命週期的引用,短生命週期在週期結束時,長生命週期仍然存在,導致無法被回收,從而造成記憶體洩漏.

看了郭神的文章,感覺這幾點比較重要,在壘程式碼的時候需要特別注意,特別記錄下來.