[Android]内存泄漏的几种方式

什么是内存泄漏?为什么会发生内存泄漏?

参见 [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 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值