Composable Functions & Previews
In the last lesson, seeing Greeting("RecipeBox") actually render meant building and
running the whole app on an emulator or device. That workflow — change a line, wait for a full
build and install, look at one screen, repeat — was one of the slowest parts of building Android UI
with traditional Views. Compose's @Preview annotation fixes this directly.
The @Preview Annotation
Adding @Preview above a zero-argument @Composable function tells Android
Studio's Compose tooling to render that composable in the design pane, right next to your code —
no emulator, no device, no app install required:
@Preview
@Composable
fun GreetingPreview() {
Greeting(name = "RecipeBox")
}
A preview function is usually a tiny wrapper, not the composable you're actually building — Android
Studio requires the annotated function to take no parameters (it needs to call it with zero
arguments to render it), so if the real composable takes data like a Recipe, the
preview function supplies sample data itself, exactly like GreetingPreview supplies the
literal string "RecipeBox" above.
Preview Parameters: showBackground, widthDp, heightDp
By default, a preview renders with a transparent background and a size that just fits its content —
fine for a quick check, but not always representative of how the composable will look inside a real
screen. A few parameters on @Preview make it more useful:
@Preview(showBackground = true, widthDp = 360, heightDp = 640)
@Composable
fun RecipeCardPreview() {
RecipeCard(title = "Tomato Soup", prepMinutes = 20)
}
| Parameter | What it does |
|---|---|
showBackground | Paints a solid (usually white, or the current theme's background) canvas behind the preview instead of leaving it transparent |
widthDp / heightDp | Fixes the preview's rendering area to a specific size in density-independent pixels, useful for approximating an actual phone screen or a fixed-size card slot |
name | A label shown above the rendered preview when you have several — helps tell them apart at a glance |
Multiple Previews on One Composable: Light and Dark
You are not limited to one @Preview per composable. Stacking several annotations on the
same function renders each one side by side, which is exactly how you'd check a composable in both
light and dark appearance without ever switching your device's theme:
@Preview(name = "Light", showBackground = true)
@Preview(name = "Dark", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun RecipeCardPreviews() {
RecipeBoxTheme {
RecipeCard(title = "Tomato Soup", prepMinutes = 20)
}
}
Wrapping the previewed content in RecipeBoxTheme { } (RecipeBox's own
MaterialTheme wrapper, covered in the Theming section of this track) matters here —
without it, the uiMode flag has nothing theme-aware to switch, and both previews would
look identical. With the theme wrapper in place, Android Studio renders both variants at once, so a
color or contrast problem in dark mode shows up immediately, instead of after you've shipped it.
Why This Beats "Run the Emulator Every Time"
The old View-based loop for a small visual tweak was: change XML or a layout param, rebuild, wait
for Gradle, wait for install, wait for the Activity to launch, navigate to the right screen, look.
For a UI-heavy screen like RecipeBox's Add/Edit Recipe form, that loop could easily cost a minute or
more per tweak. A @Preview re-renders in the IDE in a fraction of that time, and because
it's just a composable call with sample data, you can preview a component completely out of context
— a single RecipeCard, a single form field — without needing the rest of the app wired
up around it at all.