Виявлення та виправлення витоків пам'яті (Memory Leaks) мобільного додатку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Виявлення та виправлення витоків пам'яті (Memory Leaks) мобільного додатку
Складний
~3-5 днів
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Виявлення та виправлення утечок пам'яті в мобільних програмах

Програма вбиває iOS, коли користувач відкриває та закриває екран карти 20 разів підряд. Crash log містить Terminated due to memory pressure. В Instruments → Allocations видно: кожне відкриття MapViewController додає ~12 MB до heap і ці 12 MB ніколи не звільняються. Після 20 відкриттів — 240 MB тільки від екрана карти. Це утечка пам'яті — не «можливо», а точно.

Механіка утечок: чому об'єкти не звільняються

Retain cycles на iOS (ARC)

ARC лічить сильні посилання. Якщо A тримає B, а B тримає A — жоден не досягне нульового лічильника та ніколи не звільниться. Найчастіші паттерни:

Closure без [weak self]:

// УТЕЧКА
viewModel.onDataLoaded = {
    self.tableView.reloadData() // сильне посилання на self
}

// ПРАВИЛЬНО
viewModel.onDataLoaded = { [weak self] in
    self?.tableView.reloadData()
}

Timer:

// УТЕЧКА — Timer тримає target сильно
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self,
                              selector: #selector(tick), userInfo: nil, repeats: true)

При закритті ViewController timer продовжує працювати та тримає ViewController. Рішення — Timer.scheduledTimer(withTimeInterval:repeats:block:) з [weak self] в block та обов'язковий timer.invalidate() у deinit.

Delegate без weak:

// УТЕЧКА
protocol DataDelegate: AnyObject { func didLoad() }
class DataService {
    var delegate: DataDelegate? // повинен бути weak!
}

Якщо DataService живе довше делегата або обидва тримають один одного — утечка. weak var delegate: DataDelegate? — обов'язково.

Утечки на Android

Context leak — найпоширеніша:

// УТЕЧКА — Activity Context у singleton
object AppRepository {
    private var context: Context? = null
    fun init(ctx: Context) { context = ctx } // ctx — Activity
}

Activity не звільняється поки живе Repository. Використовуйте лише applicationContext у singleton-об'єктах.

Anonymous inner class + Handler:

// УТЕЧКА — анонімний клас неявно тримає посилання на Activity
private val handler = Handler(Looper.getMainLooper())
handler.postDelayed({
    updateUI() // this — неявне посилання на Activity
}, 5000)

Рішення: WeakReference<MyActivity> або lifecycleScope.launch { delay(5000); updateUI() } — coroutine отменяется разом з lifecycle.

LiveData observers без removeObserver: У Fragment підписуємося на ViewModel.liveData.observe(this, ...). Якщо this — не viewLifecycleOwner а сам Fragment — observer живе весь lifecycle Fragment, включаючи періоди коли View розрушена. При пересоздании View — додається другий observer. Після N пересозданий N observers.

Діагностика: інструменти

LeakCanary (Android) — де факто стандарт. Додайте одну залежність у debug build, він автоматично відслідковує Activity, Fragment, View, ViewModel. При виявленні утечки — сповіщення з повною retain tree. Обов'язково в будь-якому Android-проекті.

Instruments → Leaks (iOS) — будує граф об'єктів та шукає цикли. Запустіть сценарій 10–15 разів, чекайте поки Leaks почервенить. Клік на утечку — повний стек об'єктів з retain-шляхом.

Instruments → Allocations, Generation Analysis — для logical leaks (об'єкти без циклічних посилань, але які накопичуються). Mark generation перед дією → виконайте дію → подивіться що додалось та не пішло.

Android Studio Memory Profiler → Heap Dump — знімок heap з шляхом до GC root для кожного об'єкта. Шукаємо Activity екземпляри — не повинно бути більше одного (активного).

Випадок: RxJava Disposable без dispose

Flutter-розробник перейшов на Android та написав RxJava-код з Observable.interval. Підписка створювалася в onCreate, Disposable нікуди не зберігався. При кожному повороту екрану створювався новий Observer, старий продовжував працювати. Після 10 поворотів — 10 активних потоків. LeakCanary знайшов це за 2 хвилини: retained Activity через Observable → Observer → Activity reference.

Рішення: CompositeDisposable, додайте всі підписки, викличте disposables.clear() у onStop() або onDestroy().

Що ми робимо в рамках послуги

  • Додаємо LeakCanary у debug-сборку Android, налаштовуємо прогон тестових сценаріїв
  • Проводимо сесії Instruments Leaks + Allocations для iOS по всім ключовим екранам
  • Аналізуємо всі retain-шляхи знайдених утечок
  • Виправляємо: weak references, timer invalidation, proper closure capture, observer lifecycle
  • Додаємо deinit / onDestroy логування для регресійного контролю

Часові рамки

Діагностика утечок пам'яті — 1–3 дні. Виправлення виявлених утечок — 2–7 днів залежно від кількості та запущеності проблеми.