Performance & Optimisation
๐ Performance & Optimisation
๐ฌ Profiling โ Measure First
Android Studio's Profiler (View โ Tool Windows โ Profiler) attaches to a running app and shows CPU usage, memory allocation, and network activity in real time, against the actual device or emulator โ not estimates, actual measurements:
CPU Profiler
Records a method trace showing exactly which functions consumed CPU time and for how long โ the tool that turns "the app feels janky here" into "this specific function is the bottleneck."
Memory Profiler
Shows allocation over time and lets you capture a heap dump โ a snapshot of every object currently in memory, which is exactly what's needed to actually confirm a suspected memory leak rather than just guess at one.
The recurring theme across every optimization technique in this chapter: measure first, then fix the specific thing the measurement points at. Applying remember everywhere (Chapter 1) or obsessing over a function that profiling shows takes 0.1% of frame time is wasted effort compared to fixing whatever the profiler actually flags as expensive.
๐ณ๏ธ Memory Leaks
A memory leak happens when something holds a reference to an object (most dangerously, an Activity or its Context) longer than that object's actual lifetime โ the garbage collector can never reclaim it, because something still "needs" it, even though nothing legitimately does:
This is exactly why Course 2 Chapter 5 was strict about @ApplicationContext in Hilt modules rather than an arbitrary Context โ an Application-scoped context genuinely lives as long as the app does, so holding onto it long-term is safe; holding onto an Activity's Context the same way isn't. Other common sources: a listener registered on something long-lived (like a static object or a system service) and never unregistered, or a coroutine launched outside a properly-scoped CoroutineScope (Course 2, Chapter 6) that keeps running โ and keeps its captured references alive โ long after the screen using it is gone.
LeakCanary (a debug-build-only library, added as a dependency) automatically detects leaked Activities/Fragments and shows a notification with the exact reference chain keeping them alive โ turning "I suspect there's a leak somewhere" into a precise, actionable stack trace, without manually capturing and inspecting heap dumps by hand.
๐ซ ANR โ Application Not Responding
An ANR is triggered when the main thread is blocked for roughly 5 seconds โ the system shows the user a dialog offering to close the app, which is about as bad an impression as an app can make. The root cause is almost always something blocking that should have been asynchronous:
Every architectural decision from Chapters 3-6 of Course 2 โ suspend DAO/API functions, viewModelScope.launch, letting Room and Retrofit handle their own dispatching โ exists specifically to make this class of bug structurally hard to write by accident. An ANR is rarely a mystery once traced: it's almost always a blocking call that skipped the coroutine pattern this entire course has been reinforcing.
๐ Baseline Profiles โ Optimizing First Launch
Android's runtime (ART) compiles app code just-in-time as it runs, on first launch โ which means the very first time a user opens a newly-installed app, they experience the slowest possible version of it, before the JIT compiler has "warmed up." A baseline profile is a list of critical code paths (startup, common navigation flows) pre-compiled ahead of time and shipped inside the APK itself:
Running this (via a separate macrobenchmark Gradle module) both measures actual cold-start time and generates the profile data that gets bundled into the release APK โ subsequent installs benefit from ahead-of-time compilation for exactly the paths real users hit most (app launch, the first screen shown), without needing every possible code path pre-compiled.
Android Performance Metrics vs Web (Core Web Vitals)
| Web (Core Web Vitals) | Android Equivalent |
|---|---|
| LCP (Largest Contentful Paint) | Cold-start time / Time to Full Display |
| INP (Interaction to Next Paint) | Jank / dropped frames during interaction |
| CLS (Cumulative Layout Shift) | No direct equivalent โ Compose layout is more deterministic than browser reflow |
| Page freezing the browser tab | ANR (freezing the whole app) |
๐ป Coding Challenges
Challenge 1: Spot and Fix a Memory Leak
Given the AnalyticsManager singleton shown in this chapter's example (holding a raw Context), rewrite init(context: Context) to safely store only what's needed long-term (e.g. by taking context.applicationContext instead of the raw parameter). Explain in a comment why applicationContext specifically fixes the leak.
Goal: Practice recognizing and fixing the classic Context-leak pattern.
Challenge 2: Fix an ANR-Prone Function
Given a suspend fun loadUserProfile() that currently calls a blocking (non-suspend) legacy Java library function readFromDiskBlocking() directly, rewrite it to wrap that call in the correct withContext dispatcher (Course 2, Chapter 6) so it can't block the main thread when called from viewModelScope.launch.
Goal: Practice fixing a realistic ANR-prone pattern using the dispatcher knowledge from earlier in the course.
Challenge 3: Reading a Profiler Result
Given a hypothetical CPU Profiler trace showing 85% of a screen's load time spent inside a single function called parseAndSortLargeList(), and knowing this function currently re-runs on every recomposition with no memoization, explain (in a comment, referencing Chapter 1's tools specifically) what fix you'd apply and why profiling โ not guessing โ was what correctly identified this as the actual bottleneck.
Goal: Practice connecting a profiling result to the correct, already-learned fix (Chapter 1's remember).
Memory leaks are largely prevented by the same @ApplicationContext-vs-Context discipline from Course 2 Chapter 5's Hilt setup. ANRs are largely prevented by the suspend/viewModelScope pattern from Course 2 Chapters 3-6. Getting this course's architecture right the first time is, in a real sense, already most of the performance work โ this chapter mainly gave names and tools to problems the earlier patterns were already designed to avoid.
๐ฏ What's Next
Next chapter: Publishing to Google Play โ signing, the app bundle format, Play Console, the store listing, and release tracks.