什么是内存泄漏?为什么会发生内存泄漏?
参见 [Android]Handler引起内存泄漏的原因以及解决办法
Android开发中最常见的5个内存泄漏
一、单例模式造成的内存泄漏
单例模式的静态特性会使其生命周期和应用程序的生命周期一样长,说明当一个对象不再使用了,本该被GC回收,但是单例对象还在持有着该对象的引用,这时GC就无法回收该对象,造成内存泄漏。
问题代码:
public class Singleton {
private static Singleton instance;
private Context context;
private Singleton(Context context) {
this.context = context;
}
public static Singleton getInstance(Context context) {
if (instance != null) {
instance = new Singleton(context);
}
return instance;
}
}
注意Context,如果传入的是Activity的Context,该Activity被销毁,Context随即也被销毁,但是这个单例还在持有着该Activity的引用,造成内存泄漏。
如果传入的Application的Context,那就没有问题,因为Application的生命周期和应用程序的生命周期一样。
正确代码:
public class Singleton {
private static Singleton instance;
private Context context;
private Singleton(Context context) {
this.context = context.getApplicationContext();
}
public static Singleton getInstance(Context context) {
if (instance != null) {
instance = new Singleton(context);
}
return instance;
}
}
二、非静态内部类造成的内存泄漏
public class MainActivity extends AppCompatActivity {
private static TestResource mResource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mResource == null){
mResource = new TestResource();
}
//...
}
class TestResource {
//...
}
}
为什么会引起内存泄漏:因为在Activity中创建了非静态内部类,非静态内部类默认持有Activity的引用,又因为它的生命周期和应用程序一样长,所以当Activity销毁时,静态内部类的对象引用不会被GC回收,造成内存泄漏。
如何解决:
1.内部类改为静态内部类
2.将内部类封装用单例模式封装,Context使用Application的Context
三、Handler引起的内存泄漏
[Android]Handler引起内存泄漏的原因以及解决办法
四、线程引起的内存泄漏
问题代码:
new Thread(new Runnable() {
@Override
public void run() {
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}).start();
Runnable是一个匿名内部类,所以它会持有当前Activity的隐式引用。如果Activity销毁,但是线程任务还未执行完毕,就会导致Activity无法被GC回收,造成内存泄漏。
正确写法:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
new Thread(new MyRunnable()).start();
}
static class MyRunnable implements Runnable{
@Override
public void run() {
try
{
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
五、资源未及时回收造成的内存泄漏
使用完BroadcastReceiver,ContentObserver,File,Cursor,等资源是,一定要及时在合适的位置关闭,注销或者释放内存。否则GC无法回收,造成内存泄漏。
参考:
https://blog.csdn.net/qq_35373333/article/details/74909811
https://blog.csdn.net/u014005316/article/details/63258107