Использование синглтона создает утечку памяти в котлине - PullRequest
1 голос
/ 04 апреля 2019

Попытка использовать класс Singleton в другом Singleton, но каким-то образом это дает мне утечки памяти.

Как я могу улучшить это?

Вот мой пример реализации синглтона

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)
}

Класс инъекции

object Injection {
    fun provideSecondSingletonClass(context: Context): SecondSingletonClass = SecondSingletonClass.getInstance(context)
    fun provideFirstSingletonClass(context: Context): FirstSingletonClass = FirstSingletonClass.getInstance(context)
}

Так что, когда я инициализирую свойство - private val sSingletonClass или private val fSingletonClass, это приводит к утечкам памяти.Но если я назову свой одноэлементный класс где-нибудь в функциональном блоке, он будет работать нормально

Можно ли достичь того, чего я хочу?Или я должен использовать это явно ...

Ответы [ 2 ]

2 голосов
/ 04 апреля 2019

Вы пропускаете контекст здесь.Вы не должны содержать долговременную ссылку на контекст.Вместо этого вы можете использовать Context в качестве аргумента в нужных им методах FirstSingletonClass и SecondSingletonClass.

Студия Android должна выдать вам следующее предупреждение:

Не размещать классы контекста Android в статических полях (статическая ссылка на SecondSingletonClass, который имеет контекст поля, указывающий на контекст);это утечка памяти (которая также нарушает Instant Run)

Ваш код может быть упрощен до этого:

object FirstSingletonClass {
    private val sSingletonClass = SecondSingletonClass
}

object SecondSingletonClass {
    private val fSingletonClass = FirstSingletonClass
}
1 голос
/ 05 апреля 2019

Проблема: Вы передаете экземпляр контекста в синглтон, контекст может быть действием, службой и т. Д. Это может привести к утечке контекста.

Решение: Вместо 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)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...