Post #684
711
🛡️
В прошлом посте мы выяснили: Callback Hell = Memory Hell.
Вам нужно вручную отписываться в
Kotlin Coroutines предложили решение: Structured Concurrency.
И в Android это реализовано через
Как это работает на пальцах:
Сценарий: Пользователь открыл экран, запустилась загрузка (1), и он сразу нажал "Назад". Activity уничтожается.
Что происходит под капотом:
1.
2.
3. Он вызывает
4. Отмена каскадно летит вниз ко всем дочерним корутинам.
В чем магия спасения памяти?
Когда корутина отменяется в точке подвеса (suspend point, например, внутри Retrofit вызова), она выбрасывает
Стек вызовов сворачивается. Ссылки на локальные переменные и
Нам не нужно писать
⚠️ НО! Есть подвох для Сеньоров (Cooperative Cancellation)
Отмена корутин - кооперативная. Если вы пишете вычислительный код, который не саспендится,
Пример утечки процессора (CPU Leak):
Activity умрет,
Fix:
Вставляйте
Вывод:
Кто хоть раз забывал
✍️ @kotlin_lib
lifecycleScope - бро. Почему Coroutines не текут (почти)В прошлом посте мы выяснили: Callback Hell = Memory Hell.
Вам нужно вручную отписываться в
onDestroy, иначе this утечет вместе с Activity.Kotlin Coroutines предложили решение: Structured Concurrency.
И в Android это реализовано через
lifecycleScope и viewModelScope.Как это работает на пальцах:
// Внутри Fragment / Activity
lifecycleScope.launch {
val user = api.getUser() // (1) Suspend point
showUser(user) // (2) Update UI
}
Сценарий: Пользователь открыл экран, запустилась загрузка (1), и он сразу нажал "Назад". Activity уничтожается.
Что происходит под капотом:
1.
Lifecycle переходит в состояние DESTROYED.2.
lifecycleScope привязан к этому событию через LifecycleEventObserver.3. Он вызывает
cancel() у родительского Job.4. Отмена каскадно летит вниз ко всем дочерним корутинам.
В чем магия спасения памяти?
Когда корутина отменяется в точке подвеса (suspend point, например, внутри Retrofit вызова), она выбрасывает
CancellationException.Стек вызовов сворачивается. Ссылки на локальные переменные и
this (Activity) освобождаются немедленно.Нам не нужно писать
call.cancel() в onDestroy. Инфраструктура делает это за нас.⚠️ НО! Есть подвох для Сеньоров (Cooperative Cancellation)
Отмена корутин - кооперативная. Если вы пишете вычислительный код, который не саспендится,
lifecycleScope вас не спасет.Пример утечки процессора (CPU Leak):
lifecycleScope.launch(Dispatchers.Default) {
// ❌ ЭТО НЕ ОТМЕНИТСЯ АВТОМАТИЧЕСКИ
while (true) {
heavyCalculation()
// Нет точек suspension (delay, yield, IO)
}
}
Activity умрет,
Job перейдет в состояние Cancelling, но цикл продолжит крутиться в фоновом потоке, пожирая батарею, пока приложение не убьют.Fix:
Вставляйте
yield() или проверяйте isActive в тяжелых циклах.
while (isActive) { // ✅ Теперь мы проверяем флаг отмены
heavyCalculation()
}
Вывод:
lifecycleScope спасает от Memory Leaks (ссылок), но не от глупости в CPU-bound задачах.Кто хоть раз забывал
isActive в циклах и получал горячий телефон? 🔥✍️ @kotlin_lib
- 👍 3


