Android GC собирает объект, если событие имеет сильную ссылку на приложение (почему это происходит?) - PullRequest
1 голос
/ 08 апреля 2019

Как разработчик Android, я много раз слышал, что View (Activity / Fragments) не должен содержать никаких ссылок на объекты с более длинным жизненным циклом (например, Application), иначе GC не сможет собрать его и произойдет утечка памяти.

Но сегодня я попытался воспроизвести эту проблему и получил неожиданный результат - GC все еще собирает Activity, даже если она имеет ссылку на класс Application.

Я запустил его на 3 устройствах (API: 22,24,28) и получил тот же результат.

Вот код, который я использовал для теста:

Вид:

class MainActivity : AppCompatActivity() {

    var gcBlocker = ApplicationContext.inst.list

    override fun onCreate(savedInstanceState: Bundle?) {
        Log.d("custom_masher", "CREATE!")
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        gcBlocker.forEach {
            Log.d("app", it.toString())
        }
    }

    fun finalize(){
        Log.d("custom_masher", "FINALIZE!")
    }
}

Применение:

class ApplicationContext : Application() {

    var list = listOf<Int>(1, 2, 3)

    companion object {
        lateinit var inst:ApplicationContext
    }

    override fun onCreate() {
        super.onCreate()

        inst = this
    }
}

Как я воспроизвожу это:

  1. Включите «Не сохранять действия» в параметрах разработчика на устройстве Android, чтобы принудительно убить активность

  2. Скомпилируйте код выше

  3. Закройте (сверните) приложение и откройте его несколько раз. MainActivity.onCreate запускается каждый раз, когда я закрываю / открываю Activity

  4. Закрыть (свернуть) приложение

-x-> через 10-30 секунд я получил журнал, что все созданные действия были завершены (сборщик мусора)

---> созданные действия не должны собираться мусором, поскольку они содержат ссылку на класс Application

Кто-нибудь знает, почему это происходит? Значит ли это, что нам вообще не нужно беспокоиться об утечках активности? :)

PS Я также сделал ту же проблему без опции "Не сохранять действия"

1 Ответ

0 голосов
/ 08 апреля 2019

Хорошо, я понял это, когда вспомнил основные термины GC:)

GC собирает объект, когда корневой объект (приложение) не может обогатить собранный объект.

В моем случае, хотя MainActivity имеет ссылку на экземпляр приложения, экземпляр приложения по-прежнему не может обогащать какой-либо метод или свойство MainActivity, поэтому, когда Android освобождает действие, оно собирается GC.

Если я передал ссылку Activity или обратный вызов в класс Application, то MainActivity не будет собираться GC.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...