Android Handler Memory Leaks
Article Summary
Dima Voronkevych from Bumble's Android team reveals how a simple postDelayed() call can silently keep 7 Activity instances alive in memory. Even with garbage collection, your app might be one rotation away from an OutOfMemoryError.
This deep dive from Bumble's engineering team dissects Android Handler memory leaks using real heap dumps and OQL analysis. The article walks through progressively better solutions, from static inner classes to a custom library that solves the problem elegantly.
Key Takeaways
- Anonymous Runnables create indirect this$0 references that prevent Activity garbage collection
- Static classes with WeakReferences work but create unreadable boilerplate code
- Handler.removeCallbacksAndMessages(null) in onDestroy clears all pending messages cleanly
- Bumble's WeakHandler library prevents leaks while keeping code readable and maintainable
Three proven approaches fix Handler leaks: static classes with WeakReferences (verbose), manual cleanup in onDestroy (reliable), or Bumble's open source WeakHandler library (cleanest).
About This Article
Android's Handler.postDelayed() creates indirect this$0 references from anonymous Runnables to Activities. These references prevent garbage collection for the entire delay duration, causing multiple Activity instances to pile up in memory during device rotation.
Bumble's engineering team built WeakHandler, a custom library that wraps Runnables in WeakRunnable objects. This breaks the hard reference chain while keeping a hard reference to the Handler itself so it doesn't get garbage collected too early.
WeakHandler reduced retained Activity instances from seven down to one after device rotation. This eliminated the memory pressure that could trigger OutOfMemoryError crashes without requiring verbose boilerplate code or manual cleanup in onDestroy.