Skip to content

Expert: features and shipping · Testing Android apps · topic 42 of 50 · 30 min

Debugging and performance

Explanation

Find bugs with Logcat filters and the debugger: set breakpoints, step through code and inspect variables. Layout Inspector shows the live Compose tree and recomposition counts. The Android Studio Profiler measures CPU, memory and more. Common fixes for slow screens: lazy lists with keys, no heavy work in composables, remember expensive values, and always judge speed on a release build.

Debugging is a method, not luck

When something goes wrong, guessing wastes hours. A calm method works: reproduce the bug reliably, read the error or log, form a guess, check it with a tool, fix, and add a test so it cannot return. Android Studio gives you strong tools for each step.

Logcat, used well

Filter Logcat to your app (package:mine), your tag (tag:Cart) and level (level:error). Log key events with clear messages: "Checkout started, items=3". Never log passwords, OTPs, tokens or personal data, even in debug builds, because logs can be read during development and shared in bug reports.

The debugger

  1. Click in the gutter next to a line to set a breakpoint (a red dot).
  2. Run the app with the Debug button (the bug icon) instead of Run.
  3. When the line is reached, the app pauses. The Variables panel shows every value at that moment.
  4. Step Over goes to the next line; Step Into enters a function; Resume continues to the next breakpoint.
  5. Right-click a breakpoint to add a condition, for example only stop when orderId == 9081.

The debugger answers "what is actually happening" directly, instead of adding and removing dozens of log lines. You can also attach the debugger to an app that is already running.

Layout Inspector

Layout Inspector shows the live UI tree of a running app: every composable, its size and parameters. For Compose it can also show recomposition counts, how many times each composable re-ran. If a small Text recomposes hundreds of times while you scroll, something reads state too broadly; fix it before users feel the lag.

Profiler

The Android Studio Profiler measures CPU usage (which functions take the time), memory (allocations and leaks) and more while the app runs. Use it when a screen stutters or the app gets slower over time. Measure first, then optimise the part that is actually slow.

Common performance fixes in Compose

SymptomLikely causeFix
Scrolling a long list stuttersColumn with all items, or no keysLazyColumn with key = { it.id }
Screen janks on every state changeHeavy work (sorting, formatting) inside the composable bodyDo it in the ViewModel, or remember(input) { compute(input) }
Many recompositions while scrollingReading fast-changing state high in the treeRead state as low as possible; use derivedStateOf for derived values
Slow first launchHeavy work in onCreate or ApplicationLoad lazily; consider Baseline Profiles
Careful: Debug builds are much slower than release builds, especially for Compose, because debugging support and no optimisation are switched on. Always judge performance on a release build (with R8 enabled) on a real, preferably mid-range or budget, phone.

Baseline Profiles

A Baseline Profile is a list of the app's important code paths (start-up, first screen, scrolling) that ships with the app so Android can compile them ahead of time on install. Google reports noticeably faster start-up and smoother first frames for apps that use them. They are generated with the Macrobenchmark library; treat them as an expert optimisation after the basics.

Think of it like this: Debugging with breakpoints is like a cricket umpire using slow-motion replay: instead of guessing whether the ball hit the bat, you pause at the exact moment and look. The Profiler is like the speed gun: it tells you exactly how fast each delivery really was.

Common mistakes

  • Measuring speed in debug builds and "optimising" code that is fast in release.
  • Optimising without measuring first.
  • Logging sensitive data.
  • Fixing a bug without adding a test, so it comes back later.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Debugging and performance · 1/6

Reproduce → Check → Fix → Test

Debug with a method: reproduce, read the error, guess, check with a tool, fix, and add a test.

Prefer a video by a teacher? Find free videos on “android studio debugger breakpoints layout inspector compose recomposition profiler” on YouTube ↗

In real life: A laggy order history screen

Users of a food app complained that the order history stuttered. Layout Inspector showed each row recomposing on every scroll frame, because each row formatted dates and prices inside the composable from a shared state object. The developer moved formatting into the ViewModel, added keys to the LazyColumn, and checked on a release build on a budget phone: scrolling became smooth.

kotlin
// Before: formatting inside the row on every recomposition
// Text(SimpleDateFormat("dd MMM yyyy").format(Date(order.time)))

// After: formatted once in the ViewModel's UiState
data class OrderRowUi(val id: Long, val dateText: String, val amountText: String)

// LazyColumn { items(rows, key = { it.id }) { OrderRow(it) } }
Prepare display data once; let rows just show it.

Practice (0/3 done)

Task 1 · Question

Your Compose screen feels slow in a debug build. What should you do first?

Task 2 · Question

Which tool shows how many times each composable recomposed?

Task 3 · Practice

Take a list screen from your app. (1) Set a conditional breakpoint that pauses only for one specific item id and inspect its values. (2) Open Layout Inspector and note the recomposition counts while scrolling. (3) Fix one cause of extra work (keys, moving formatting to the ViewModel, or remember). (4) Compare scrolling in debug and release builds.

Quick quiz

Question 1

1.What does a breakpoint do?

Question 2

2.Which is a common cause of janky Compose screens?

Question 3

3.What are Baseline Profiles for?

Question 4

4.Which should you never log?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What does a breakpoint do?

Answer: Pauses execution at a line so you can inspect values

Run in Debug mode to use it.

Which is a common cause of janky Compose screens?

Answer: Heavy work like sorting or formatting inside composable bodies

Move work to the ViewModel or remember it.

What are Baseline Profiles for?

Answer: Improving start-up and early frame performance through ahead-of-time compilation of key paths

They ship hints to compile hot code early.

Which should you never log?

Answer: Passwords and OTPs

Logs must not contain secrets or personal data.

Which function shows Compose content in an activity?Related

Answer: setContent

setContent { } hosts the composables.

From Hello Compose: your first screen

What does "Step Into" do in a debugger?Related

Answer: Goes inside the method called on the current line

Step Into enters the called method.

From Reading errors and debugging

What is recomposition?Related

Answer: Compose re-running composables that read changed state

Only affected composables re-run.

From State and recomposition

Why is debug mode not good for judging speed?Related

Answer: It adds checks and hot reload support that slow it down

Use profile mode.

From Performance

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. This is the last topic of “Testing Android apps”. The module exam comes next.
  2. Module 10 exam: Testing Android apps · 12 questions · 25 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Publishing on the Play Store and Firebase. 50 topics left in the course before the final exam.

← Previous: Compose UI tests