Android中内存泄漏的几种情况

来源:互联网 发布:淘宝保养品店铺推荐 编辑:程序博客网 时间:2024/06/06 01:01

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或关闭,都会造成内存泄漏.


造成内存泄漏的主要原因是长生命周期持有短生命周期的引用,短生命周期在周期结束时,长生命周期仍然存在,导致无法被回收,从而造成内存泄漏.


看了郭神的文章,感觉这几点比较重要,在垒代码的时候需要特别注意,特别记录下来.



原创粉丝点击