Based on the book Programming Android in Kotlin, we get into the weeds exploring Android memory and threading and how memory leaks have influenced the evolution of development.
Coroutines in Practice 2018 2009 Android Developer Blog: Avoiding memory leaks 2016 KT-1622: Coroutine does not clear internal state Fixed Kotlin 1.4 2019 Roman Elizarov: Structured Concurrency
resources in hardware capacity ◦ ~15% of Android users use Lollipop and below on their devices¹ • Memory leaks can cause "jank", OOM, and other strange behaviors ¹ Bradshaw, Kyle. “Google Kills Android Distribution Numbers on the Web - 9to5Google.” 9To5Google
RAM pages across several processes via paging. • At application initialization, a program in the OS called Zygote forks a new VM instance. • The VM creates a store for dynamic memory allocation called the heap. ◦ A shared store for all pages to be temporarily stored in memory
heap ◦ If your app reaches heap capacity and tries to allocate for more memory, it will receive an OOM • The ART heap organizes objects by age and size ◦ Younger Generation (minor) ◦ Older Generation (major) ◦ Permanent Generation (major)
a self-managed memory environment • Will free allocated memory back to the heap • GC will: ◦ Find data objects in a program that cannot be reached in the future ◦ Reclaim the resources used by those objects • Objects eligible for GC: ◦ Nullifying the object reference ◦ Re-assigning the object reference ◦ Object created inside method
there is battery drainage. ◦ Excessive paging swaps, checks, clears ◦ Camera, location, graphics, wifi radio • GC will help manage the heap, but too many calls for GC can block the UI ◦ Be frugal with memory allocation! • Too much memory consumption can lead to "jank", OutOfMemory exceptions, and other strange behaviors
and views • Allows Android components in the application to interact with the Android OS • All components run within the same process instantiates on the UI thread
etc) has a lifecycle of its own • Killing an Activity or even the UI Thread does not necessarily kill a background thread • Do not block the UI thread! • Do not access the UI toolkit from outside the UI Thread • Force the top-level activity/fragment to be the sole system responsible for updating UI objects
Android Activity or Context or View or another Android UI toolkit component into background threading • Holding an activity or view or context as a static reference Explicit Memory Leaks class AlertDialogCreator(val context: Context) { companion object { fun buildDialog(context: Context, title: String, positive: String) = AlertDialog.Builder(context) .setPositiveButton(positive, null) .show() } }
Coroutines in Practice 2018 2009 Android Developer Blog: Avoiding memory leaks 2016 KT-1622: Coroutine does not clear internal state Fixed Kotlin 1.4 2019 Roman Elizarov: Structured Concurrency Android deprecates AsyncTask
not the Fragment itself) is destroyed when a Fragment is put on the backstack² ◦ Developers are expected to clear refs for views in Fragment::onDestroyView • Be wary of third-party libraries that may reference the use of an Android resource ¹ “Issue 145468285: Memory Leak with Nested Fragments and Data Binding.” Issuetracker.google.com, Google, 2 Dec. 2019, 09:01am PT, issuetracker.google.com/issues/145468285#comment6.
you interact with the Android API Framework • Follow the constraints of the Android threading model • Profile your app with AS or LeakCanary • Ask yourself "could I be interacting with a hardware component"? ◦ Databases, networking, Android graphics, location, etc etc
references, since they are stored longest in heap ◦ Never store Android components like Activities, Services, views, etc. • Do not reference Activities/Views/Fragments/Context and other Android components outside the UI thread • Use Glide if you can, but if you have to work with bitmaps, make sure to recycle/nullify • Avoid the use of persistent services whenever possible