|Memory Leaks are not apparent during development
Let's get the basics right. As much as we'd like to think of Java's Garbage Collector as our reliable agent to cleanse heap of stale objects, it's not hundred percent fool-proof, in that some of the overlooked coding gotchas can trip its reliability. For instance, a WeakReferenced object gets garbage collected quickly over its Strongly Referenced object. But that said, using WeakReferenced object comes in the way of elegant coding. So, typically you look for for areas where you can introduce WeakReference.
ProTip #1: Where possible, use the context-application instead of a context-activity. Look for opportunities where the Application-context is sufficient, instead of the Activity-context.
ProTip #2: Have ImageViews in Activity/Fragment? Use WeakReference to hold the ImageView, so that when the Activity/Fragment is destroyed, the ImageView is readily Garbage Collected.
ProTip #3: Replace non-static anonymous inner-classes (whose life-cycle is not in your control) with static inner-classes. In Java, the non-static inner-classes, hold an implicit reference to its containing class. So imagine you use a non-static inner class inside of your activity. Even after the activity is past the onDestroy life-cycle, it wouldn't be garbage collected, because the non-static inner class holds an implicit reference to it.
ProTip #4: Using Handler? Then don't forget to call removeCallbacksAndMessages(null) or removeCallbacks(mRunnable) in the onDestroy() lifecycle method of the class containing it.
ProTip #5: Using any Listeners? Remember to unregister those listeners.
ProTip #6: Using Eventbus? If you cared to use register(this) then also do care to use unregister(this) in the appropriate lifecycle method definition.
ProTip #7: Employed MVP design-pattern for your code-structure? Passing View implementation as constructor argument to your Presenter implementation? Then ensure to wrap your View in WeakReference.
ProTip #8: Using Threads? Then double-check to see if you have control over its death and are in-fact stopping it at some point in time. Threads in Java are GC roots. Therefore, the Dalvik Virtual Machine (or the DVM) keeps hard references to all active threads in the runtime system, and as a result, threads that are left running will never be eligible for garbage collection.
For detailed and informative reading do care to refer the following posts/articles/books