单例使用会在 kotlin 中造成内存泄漏
Singleton usage creates memory leak in kotlin
尝试在另一个单例中使用单例 class,但不知何故它让我出现内存泄漏。
我该如何改进它?
这是我的示例单例实现
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)
}
SecondSingletonClass块
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)
}
注入class
object Injection {
fun provideSecondSingletonClass(context: Context): SecondSingletonClass = SecondSingletonClass.getInstance(context)
fun provideFirstSingletonClass(context: Context): FirstSingletonClass = FirstSingletonClass.getInstance(context)
}
因此,当我初始化 属性 - private val sSingletonClass
或 private val fSingletonClass
时,它会产生内存泄漏。但是如果我在函数块的某处调用我的单例 class 它工作正常。
是否可以实现我想要的?或者我应该明确地使用它...
你在这里泄露了上下文。您不应该持有对 Context 的长期引用。您可以将上下文作为需要它们的 FirstSingletonClass 和 SecondSingletonClass 方法中的参数。
Android 工作室应该给你这个警告:
不要将 Android 上下文 类 放在静态字段中(对 SecondSingletonClass 的静态引用,其中的字段上下文指向 Context);这是一个内存泄漏(并且还会破坏 Instant 运行)
您的代码可以简化为:
object FirstSingletonClass {
private val sSingletonClass = SecondSingletonClass
}
object SecondSingletonClass {
private val fSingletonClass = FirstSingletonClass
}
问题:您正在将上下文实例传递给单例,上下文可能是 activity、服务等。它可能会导致上下文泄漏.
解决方法:改用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)
}
尝试在另一个单例中使用单例 class,但不知何故它让我出现内存泄漏。
我该如何改进它?
这是我的示例单例实现
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)
}
SecondSingletonClass块
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)
}
注入class
object Injection {
fun provideSecondSingletonClass(context: Context): SecondSingletonClass = SecondSingletonClass.getInstance(context)
fun provideFirstSingletonClass(context: Context): FirstSingletonClass = FirstSingletonClass.getInstance(context)
}
因此,当我初始化 属性 - private val sSingletonClass
或 private val fSingletonClass
时,它会产生内存泄漏。但是如果我在函数块的某处调用我的单例 class 它工作正常。
是否可以实现我想要的?或者我应该明确地使用它...
你在这里泄露了上下文。您不应该持有对 Context 的长期引用。您可以将上下文作为需要它们的 FirstSingletonClass 和 SecondSingletonClass 方法中的参数。
Android 工作室应该给你这个警告:
不要将 Android 上下文 类 放在静态字段中(对 SecondSingletonClass 的静态引用,其中的字段上下文指向 Context);这是一个内存泄漏(并且还会破坏 Instant 运行)
您的代码可以简化为:
object FirstSingletonClass {
private val sSingletonClass = SecondSingletonClass
}
object SecondSingletonClass {
private val fSingletonClass = FirstSingletonClass
}
问题:您正在将上下文实例传递给单例,上下文可能是 activity、服务等。它可能会导致上下文泄漏.
解决方法:改用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)
}