单例模式引起的内存泄漏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lijia1201900857/article/details/82877316

单例模式是我们项目中经常使用的一个设计模式,但是如果使用不当,也会引发内存泄漏。

例如: 下面这种常见的写法,传了一个Context 进去

import android.content.Context;

public class Utils {
    private Context mContext;
    private static Utils utils;

    private Utils(Context mContext) {
        this.mContext = mContext;
    }

    public static Utils getInstance(Context mContext) {
        if (utils == null) {
            synchronized (Utils.class) {
                if (utils == null) {
                    utils = new Utils(mContext);
                }
            }
        }
        return utils;
    }
}

当我们使用的时候:

public class MainActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Utils.getInstance(this);
    }
}

我们先运行一下,并通过 Android studio 自带的内存检测工具测试一下当前的内存使用情况

注意:android studio  3.0 的内存测试工具 是 Profiler  ,android studio 3.0 之前使用的是 anroid  Monitor 

这里我的android studio 的版本是3.0以上的

先看一下第一次运行时的内存占用情况

然后旋转一次屏幕之后

可以看到,内存使用大小有所上升。在多旋转几次

可以看到有明显的上升。

我们点击 一个向下的箭头按钮,查看分析日志

可以看到,当前存在多个 MainActivity 的实例。

然后我们手动 gc(箭头左边的 垃圾桶按钮),正常情况下,只会存在一个 MainActivity 实例,但是,我们多次gc后返现,仍然存在两个MainActivity 的实例,如图:

这就说明,已经产生了内存泄漏,GC 已经不能掌控这部分内存了。

 

原因:

首先,我们的单例模式使用的是 static 修饰的,我们知道,static 修饰的对象会一直存在内存中

 我们在 MainActivity  的onCreat() 方法中 ,调用了  Utils.getInstance(this)。把ManActicity 传了进入,创建了 Utils 的实例。

当我们旋转屏幕的时候,MainActivity  会走 onDestory() 方法,但是 当前MainAcivity 被 Utils对象 持有引用,

并不会被销毁,然后 再次走onCreate()  方法,方法中 再次调用 Utils.getInstance(this),会把 新的MainActivity 对象传进去

但是:  当前 的Utils 实例并不为null ,条件判断走不进去,会直接返回 utils。

    public static Utils getInstance(Context mContext) {
        if (utils == null) {
            synchronized (Utils.class) {
                if (utils == null) {
                    utils = new Utils(mContext);
                }
            }
        }
        return utils;
    }

所以产生内存泄漏。

解决:

只需要把当前类的上下文,改为application就行

此时 我们旋转屏幕,MainActivity 重写加载。

猜你喜欢

转载自blog.csdn.net/lijia1201900857/article/details/82877316
今日推荐