702просмотров
33.1%от подписчиков
11 февраля 2026 г.
Score: 772
💀 Невидимый this: Как одна лямбда может утечь всю Activity Мы привыкли считать, что Kotlin умнее Java. В Java анонимный класс всегда держал ссылку на внешний класс. В Kotlin компилятор пытается оптимизировать лямбды и делать их статическими синглтонами. Но эта магия ломается от одного прикосновения. Представьте код во ViewModel или Presenter: class HeavyScreen { private val bigData = ByteArray(1024 1024 20) // 20 MB private val title = "Profile" fun load() { ExternalService.fetchData { result -> // (1) Просто логируем результат println("Got result: $result") // (2) А теперь раскомментируйте эту строку: // println("Update for $title: $result") } }
} Разбор полетов: 1. Сценарий (1): Вы не обращаетесь к свойствам HeavyScreen внутри лямбды.
Kotlin компилирует эту лямбду как static instance. Ссылки на HeavyScreen нет. Если экран закроется, GC спокойно его соберет, даже если ExternalService будет грузить данные еще 10 минут. 2. Сценарий (2): Вы добавили обращение к title.
Всё. Оптимизация отключена.
Чтобы прочитать title, лямбде нужна ссылка на инстанс HeavyScreen. Компилятор скрыто передает this в конструктор лямбды. Цепочка утечки:
ExternalService (static/singleton) -> Lambda -> this$0 (HeavyScreen) -> bigData (20 MB). Пока ExternalService держит коллбэк - ваши 20 Мб висят в памяти, даже если пользователь давно ушел с экрана. Как проверить себя?
Если вы передаете лямбду в объект, который живет дольше, чем ваш класс (Network Client, Singleton, Event Bus, Handler): 1. Убедитесь, что вы отписываетесь (clear references). 2. Или не захватывайте контекст (this) внутри лямбды (используйте только аргументы лямбды). 3. Используйте WeakReference, если архитектура позволяет (но это костыль). Совет: В IntelliJ IDEA/Android Studio включите подсветку "Implicit usage of 'this'". Это спасет вам гигабайты RAM. Кто ловил OutOfMemoryError из-за забытого коллбэка? 👇 ✍️ @kotlin_lib