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)
}
ParameterWhat it does
showBackgroundPaints a solid (usually white, or the current theme's background) canvas behind the preview instead of leaving it transparent
widthDp / heightDpFixes 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
nameA 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.

Note: Previews only ever run the composable in isolation with whatever sample data you hand it — they never talk to a real ViewModel, database, or network call. That tradeoff is exactly what makes them fast; wiring previews to fake-but-representative data is a skill worth practicing early.

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.

Next up: Previews show static UI, but RecipeBox needs interactive UI — a favorite button that changes when tapped. State: remember & mutableStateOf introduces the tool that makes that possible.