DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Compose Preview & Version Catalog — Boost Your Android Dev Workflow

Compose Preview & Version Catalog — Boost Your Android Dev Workflow

Android development has evolved dramatically in the past few years. Two features stand out as productivity multipliers: Jetpack Compose Preview and Version Catalog in Gradle. Let's explore how they work and why you should use them.

Compose Preview: See Your UI Instantly

The @Preview annotation lets you render composables directly in Android Studio without building and running on a device. This is a game-changer for UI development.

Basic Preview

@Preview
@Composable
fun GreetingPreview() {
    MyAppTheme {
        Greeting("Android")
    }
}
Enter fullscreen mode Exit fullscreen mode

Click the preview pane and you'll see your composable rendered instantly. No emulator startup, no APK build.

Multiple Previews: Light, Dark, Devices, Font Scales

A single screen needs to work across different configurations. Compose Preview makes this trivial:

// Light mode
@Preview(name = "Light Mode")
@Composable
fun GreetingLightPreview() {
    MyAppTheme(darkTheme = false) {
        Greeting("Android")
    }
}

// Dark mode
@Preview(name = "Dark Mode", uiMode = UI_MODE_NIGHT_YES)
@Composable
fun GreetingDarkPreview() {
    MyAppTheme(darkTheme = true) {
        Greeting("Android")
    }
}

// Different device sizes
@Preview(name = "Phone", device = Devices.PHONE)
@Preview(name = "Tablet", device = Devices.TABLET)
@Preview(name = "Foldable", device = Devices.FOLDABLE)
@Composable
fun GreetingDevicesPreview() {
    MyAppTheme {
        Greeting("Android")
    }
}

// Font scales
@Preview(name = "Small Font", fontScale = 0.75f)
@Preview(name = "Large Font", fontScale = 1.5f)
@Composable
fun GreetingFontScalePreview() {
    MyAppTheme {
        Greeting("Android")
    }
}
Enter fullscreen mode Exit fullscreen mode

PreviewParameterProvider: Dynamic Test Data

Instead of hardcoding preview values, use PreviewParameterProvider to test multiple states:

class GreetingPreviewParameterProvider : PreviewParameterProvider<String> {
    override val values = sequenceOf(
        "Alice",
        "Bob",
        "Charlie",
        "Device with very long name that might break UI"
    )
}

@Preview
@Composable
fun GreetingWithParameterPreview(
    @PreviewParameter(GreetingPreviewParameterProvider::class) name: String
) {
    MyAppTheme {
        Greeting(name)
    }
}
Enter fullscreen mode Exit fullscreen mode

Now you'll see four preview tiles, one for each name. Perfect for catching edge cases.

Custom Preview Annotations

Reduce boilerplate by creating custom preview annotations:

@Preview(
    name = "Default",
    showBackground = true,
    backgroundColor = 0xFFFFFFFF,
    fontScale = 1f
)
@Preview(
    name = "Dark",
    showBackground = true,
    backgroundColor = 0xFF000000,
    fontScale = 1f,
    uiMode = UI_MODE_NIGHT_YES
)
annotation class DefaultPreview

// Now use it everywhere:
@DefaultPreview
@Composable
fun MyButtonPreview() {
    Button(onClick = {}) {
        Text("Click me")
    }
}
Enter fullscreen mode Exit fullscreen mode

Interactive Mode

Click "Interactive" in the preview pane to interact with your composable like a real user—click buttons, scroll, input text. Test user interactions without running on a device.


Version Catalog: Dependency Management at Scale

Managing library versions across multiple modules is painful. Version Catalog centralizes it in one file: libs.versions.toml.

libs.versions.toml Structure

[versions]
agp = "8.1.0"
kotlin = "1.9.20"
compose = "1.5.4"
hilt = "2.48"

[libraries]
androidx-core = "androidx.core:core:1.12.0"
androidx-appcompat = "androidx.appcompat:appcompat:1.6.1"
compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "compose" }
compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "compose" }
compose-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "compose" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }

[bundles]
compose = ["compose-ui", "compose-material3", "compose-foundation"]
hilt = ["hilt-android", "hilt-compiler"]

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
hilt-plugin = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
Enter fullscreen mode Exit fullscreen mode

Using Aliases in build.gradle.kts

Once libs.versions.toml is set up, Android Studio generates type-safe accessors:

// build.gradle.kts (Module: app)
plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
    alias(libs.plugins.hilt.plugin)
}

android {
    compileSdk = 34
    // ...
}

dependencies {
    implementation(libs.androidx.core)
    implementation(libs.androidx.appcompat)
    implementation(libs.bundles.compose)
    implementation(libs.hilt.android)
    kapt(libs.hilt.compiler)
}
Enter fullscreen mode Exit fullscreen mode

No more string-based version management. If you update [versions] compose = "1.6.0", all Compose libraries update automatically.

Multi-Module Benefits

Imagine your project structure:

app/
  build.gradle.kts
core/
  build.gradle.kts
features/
  feature_home/
    build.gradle.kts
  feature_settings/
    build.gradle.kts
gradle/
  libs.versions.toml
Enter fullscreen mode Exit fullscreen mode

Every module uses the same versions from libs.versions.toml. Want to upgrade Compose across your entire project? Change one line in the TOML file. Done.


The Workflow in Action

  1. Design: Create a composable, add @Preview
  2. Iterate: Adjust colors, spacing, text. See changes instantly in the preview pane
  3. Validate: Use @PreviewParameter to test edge cases (long text, empty state, error state)
  4. Test Interactions: Switch to interactive mode, click buttons, verify navigation
  5. Version Management: Update a single version in libs.versions.toml, rebuild, all modules are in sync

This workflow cuts iteration time dramatically. No waiting for emulator startup or APK builds.


Key Takeaways

  • @Preview lets you design and test UI without a device
  • PreviewParameterProvider tests multiple states automatically
  • Custom preview annotations reduce boilerplate across your codebase
  • Interactive mode lets you test user interactions in the IDE
  • libs.versions.toml centralizes dependency management for all modules
  • Type-safe aliases prevent version conflicts and typos

Your Android development workflow will be significantly faster and more reliable.


Ready to build Android apps at scale? Check out our 8 Android App Templateshttps://myougatheax.gumroad.com

Top comments (0)