Android GC собирает объект, если событие имеет сильную ссылку на приложение (почему это происходит?)

1

Как разработчик 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 Я также сделал ту же проблему без опции "Не держать деятельность"

Теги:
garbage-collection

1 ответ

0

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

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню