🧩 Common Android Leak Patterns - Real‑World Traps LeakCanary Catches

 

Introduction

In Part 5, we explored how Shark quantifies leaks with dominator trees and retained size. But theory only gets us so far. Let’s look at the real‑world leak patterns that plague Android apps — the ones LeakCanary was built to catch.

These examples are code‑driven, diagram‑supported, and exactly the kind of content that sparks discussion in the Android community.

1. Static Context Reference

object ContextHolder {
var context: Context? = null
}
  • ❌ Holding a Context in a static field prevents GC.
  • If it’s an Activity context, the entire UI tree leaks.

Diagram:

GC RootContextHolderActivityViews

2. Anonymous Inner Class Leak

class LeakyActivity : AppCompatActivity() {
private val runnable = Runnable {
// references outer Activity
}
}
  • Inner classes hold implicit references to their outer class.
  • If posted to a long‑lived thread, the Activity leaks.

3. Handler Leak

class LeakyActivity : AppCompatActivity() {
private val handler = Handler(Looper.getMainLooper())
override fun onCreate(savedInstanceState: Bundle?) {
handler.postDelayed({ /* work */ }, 60000)
}
}
  • ❌ Delayed messages keep the Activity alive until executed.
  • Fix: use lifecycleScope or clear messages in onDestroy().

4. InputMethodManager Leak

val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(editText, 0)
  • Known framework leak: IMM holds references to destroyed Views.
  • LeakCanary categorises this as a framework leak.

5. Fragment View Leak

class MyFragment : Fragment() {
private var binding: ViewBinding? = null
override fun onDestroyView() {
super.onDestroyView()
// ❌ Forgetting to clear binding leaks the View hierarchy
}
}
  • Fix: set binding = null in onDestroyView().

📊 Diagram: Leak Patterns Overview

Static Context → Activity leak
Inner Class → Activity leak
Handler → Delayed message leak
IMM → Framework leak
Fragment Binding → View leak

🚨 Why These Patterns Matter

  • They’re common: almost every Android team has hit one.
  • They’re silent: no crash until heap fills up.
  • They’re actionable: LeakCanary surfaces them with clear traces.

🔮 Coming Next

In Part 7, we’ll explore Integrating LeakCanary in CI/CD — how to automate leak detection in pipelines, export reports, and catch regressions before release.

Comments

Featured Articles

Optimize Jetpack Compose: Performance & Best Practices

JIT vs AOT Compilation | Android Runtime

From ‘Master’ to ‘Main’: The Meaning Behind Git’s Naming Shift

Play Store Uploads with Fastlane Supply - 4

Cracking Android SDE2/SDE3 Interviews in 2026: Deep Dives, Code, Follow-ups

Android Device Security: Sandboxing, Rooting, and Attestation Explained