单例使用会在Kotlin中造成内存泄漏

时间:2019-04-04 17:13:29

标签: android kotlin singleton

试图在另一个Singleton中使用Singleton类,但是不知何故它给了我内存泄漏。

我该如何改善?

这是我的单例实现示例

foreach

SecondSingletonClass块

class FirstSingletonClass(val context: Context) {
    companion object {
        @Volatile
        private var instance: FirstSingletonClass? = null

        fun getInstance(context: Context): FirstSingletonClass =
                instance ?: synchronized(this) {
                    instance ?: FirstSingletonClass(context).also { instance = it }
                }

    }

   private val sSingletonClass: SecondSingletonClass = Injection.provideSecondSingletonClass(context)
}

注射类

class SecondSingletonClass(val context: Context) {
    companion object {
        @Volatile
        private var instance: SecondSingletonClass? = null

        fun getInstance(context: Context): SecondSingletonClass =
                instance ?: synchronized(this) {
                    instance ?: SecondSingletonClass(context).also { instance = it }
                }

    }

   private val fSingletonClass: FirstSingletonClass = Injection.provideFirstSingletonClass(context)
}

因此,当我初始化属性-object Injection { fun provideSecondSingletonClass(context: Context): SecondSingletonClass = SecondSingletonClass.getInstance(context) fun provideFirstSingletonClass(context: Context): FirstSingletonClass = FirstSingletonClass.getInstance(context) } private val sSingletonClass时,会产生内存泄漏。但是,如果我将在功能块中的某个地方调用我的单例类,则效果很好。

有可能实现我想要的吗?还是我应该明确使用它...

2 个答案:

答案 0 :(得分:2)

您正在此处泄漏上下文。您不应持有对Context的长期引用。相反,可以在需要它们的FirstSingletonClass和SecondSingletonClass方法中将Context作为参数。

Android Studio应该向您发出此警告:

请勿将Android上下文类放在静态字段中(静态引用SecondSingletonClass的字段上下文指向Context);这是内存泄漏(还会中断即时运行)

您的代码可以简化为:

object FirstSingletonClass {
    private val sSingletonClass = SecondSingletonClass
}

object SecondSingletonClass {
    private val fSingletonClass = FirstSingletonClass
}

答案 1 :(得分:1)

问题::您要将Context实例传递到Singleton中,该上下文可能是活动,服务等。这可能会使上下文泄漏。

解决方案::改为使用applicationContext

class FirstSingletonClass(val context: Context) {
    companion object {
        @Volatile
        private var instance: FirstSingletonClass? = null

        fun getInstance(context: Context): FirstSingletonClass =
            instance ?: synchronized(this) {
                instance ?: FirstSingletonClass(context.applicationContext).also { instance = it }
            }
    }

    private val sSingletonClass: SecondSingletonClass = Injection.provideSecondSingletonClass(context)
}

class SecondSingletonClass(val context: Context) {
    companion object {
        @Volatile
        private var instance: SecondSingletonClass? = null

        fun getInstance(context: Context): SecondSingletonClass =
            instance ?: synchronized(this) {
                instance ?: SecondSingletonClass(context.applicationContext).also { instance = it }
            }

    }

    private val fSingletonClass: FirstSingletonClass = Injection.provideFirstSingletonClass(context)
}