Detecting and Fixing Memory Leaks in Mobile App

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Detecting and Fixing Memory Leaks in Mobile App
Complex
~3-5 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Detecting and Fixing Memory Leaks in Mobile Applications

Application kills iOS when user opens and closes map screen 20 times in a row. Crash log contains Terminated due to memory pressure. In Instruments → Allocations visible: each opening of MapViewController adds ~12 MB to heap and these 12 MB are never released. After 20 openings — 240 MB from map screen alone. This is memory leak — not "possibly", but definitely.

Memory Leak Mechanics: Why Objects Are Not Released

Retain Cycles on iOS (ARC)

ARC counts strong references. If A holds B, and B holds A — neither reaches zero count and never gets released. Most frequent patterns:

Closure without [weak self]:

// LEAK
viewModel.onDataLoaded = {
    self.tableView.reloadData() // strong reference to self
}

// CORRECT
viewModel.onDataLoaded = { [weak self] in
    self?.tableView.reloadData()
}

Timer:

// LEAK — Timer holds target strongly
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self,
                              selector: #selector(tick), userInfo: nil, repeats: true)

When ViewController is closed, timer continues working and holds ViewController. Solution — Timer.scheduledTimer(withTimeInterval:repeats:block:) with [weak self] in block, and mandatory timer.invalidate() in deinit.

Delegate without weak:

// LEAK
protocol DataDelegate: AnyObject { func didLoad() }
class DataService {
    var delegate: DataDelegate? // must be weak!
}

If DataService lives longer than delegate or both hold each other — leak. weak var delegate: DataDelegate? — mandatory.

Leaks on Android

Context leak — most common:

// LEAK — Activity Context in singleton
object AppRepository {
    private var context: Context? = null
    fun init(ctx: Context) { context = ctx } // ctx — Activity
}

Activity is not released while Repository lives. Use only applicationContext in singleton objects.

Anonymous inner class + Handler:

// LEAK — anonymous class implicitly holds reference to Activity
private val handler = Handler(Looper.getMainLooper())
handler.postDelayed({
    updateUI() // this — implicit reference to Activity
}, 5000)

Solution: WeakReference<MyActivity> or lifecycleScope.launch { delay(5000); updateUI() } — coroutine is cancelled together with lifecycle.

LiveData observers without removeObserver: In Fragment we subscribe to ViewModel.liveData.observe(this, ...). If this — not viewLifecycleOwner but Fragment itself — observer lives entire Fragment lifecycle, including periods when View is destroyed. After View recreation — second observer added. After N recreations N observers.

Diagnostics: Tools

LeakCanary (Android) — de facto standard. Add one dependency to debug build, it automatically tracks Activity, Fragment, View, ViewModel. When leak detected — notification with full retain tree. Mandatory in any Android project.

Instruments → Leaks (iOS) — builds object graph and searches for cycles. Run scenario 10–15 times, wait for Leaks to turn red. Click on leak — full object stack with retain-path.

Instruments → Allocations, Generation Analysis — for logical leaks (objects without cyclic references, but that accumulate). Mark generation before action → execute action → see what added and didn't leave.

Android Studio Memory Profiler → Heap Dump — heap snapshot with path to GC root for each object. Look for Activity instances — shouldn't be more than one (active).

Case: RxJava Disposable without Dispose

Flutter developer switched to Android and wrote RxJava code with Observable.interval. Subscription created in onCreate, Disposable nowhere stored. On each screen rotation new Observer created, old continued working. After 10 rotations — 10 active threads. LeakCanary found it in 2 minutes: retained Activity through Observable → Observer → Activity reference.

Solution: CompositeDisposable, add all subscriptions, call disposables.clear() in onStop() or onDestroy().

What We Do Within Service

  • Add LeakCanary to Android debug build, configure test scenario runs
  • Conduct Instruments Leaks + Allocations sessions for iOS on all key screens
  • Analyze all retain-paths of found leaks
  • Fix: weak references, timer invalidation, proper closure capture, observer lifecycle
  • Add deinit / onDestroy logging for regression control

Timeframe

Memory leak diagnostics — 1–3 days. Fixing identified leaks — 2–7 days depending on quantity and severity of issues.