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或關閉,都會造成記憶體洩漏.
造成記憶體洩漏的主要原因是長生命週期持有短生命週期的引用,短生命週期在週期結束時,長生命週期仍然存在,導致無法被回收,從而造成記憶體洩漏.
看了郭神的文章,感覺這幾點比較重要,在壘程式碼的時候需要特別注意,特別記錄下來.