Your first steps with Jetpack Compose for Android development

The Android landscape is shifting as Google pushes Jetpack Compose as the recommended toolkit for native user interfaces. For developers in Sydney, Melbourne, Brisbane or Perth, this represents a fundamental change in how apps are crafted. Instead of crafting XML layouts and wiring them up in Kotlin or Java, teams describe what the screen should look like for a given state, and the framework handles the rendering. This declarative model feels natural to anyone who has worked with React or Flutter, but it is purpose built for the Android ecosystem.

Australian studios are adopting Compose at a brisk pace. Atlassian in Sydney has experimented with Compose for internal tools, while teams at Canva have explored its potential for rapid prototyping. Local meetups, from the Google Developer Group in Melbourne to the Brisbane Android community, frequently feature talks on adoption stories. Solo developers building niche apps for the Australian market find Compose reduces boilerplate and speeds iteration.

This guide walks through the foundations you need to build production ready screens. You will learn what makes Compose different from the old view system, how to set up a project, how composables work, how to manage state, and how to test on a device or emulator. By the end, you can refactor an existing screen or start a brand new app.

Understanding the declarative shift

The traditional Android UI toolkit follows an imperative pattern. You inflate an XML layout, find views by id, and mutate them through code. Compose turns this on its head. You write functions that emit UI elements, and when the underlying data changes, the framework recomposes only the parts that need updating.

This approach aligns with functional programming ideas that many Australian developers have encountered through Kotlin. Functions annotated with @Composable are pure in the sense that given the same inputs they produce the same output, and side effects are handled explicitly. The mental model is closer to designing a React component than juggling findViewById calls in a RecyclerView adapter.

The practical payoff is significant. Code that used to require a layout file, an adapter, and several setters can often be expressed in a few dozen lines of Kotlin. Screens become easier to read, and theming is handled through a consistent design system rather than scattered style attributes.

Preparing your development environment

You will need Android Studio Hedgehog or a newer stable release, with a live preview pane that updates as you type. Install the Android SDK, an emulator image, and the latest Kotlin plugin. Most Australian developers run macOS or Windows; Linux setups work fine for command line builds, though the official emulator is smoothest on macOS.

Create a new project and choose the Empty Activity template, making sure the language is Kotlin and the minimum SDK is at least API 21. Compose supports older devices, so you can target the bulk of the Australian market. Open the build.gradle file and confirm that the Compose dependencies are present and that composeCompilerVersion matches your Kotlin version.

Many Australian teams adopt a monorepo or modular structure, so familiarise yourself with how Compose libraries are declared. The BOM approach lets you specify a single version that aligns the Compose runtime, UI, material3, and tooling artifacts. This keeps upgrades tidy and avoids the version mismatch errors that can stall a build.

Composables, modifiers and the building blocks

Every piece of UI in Compose is a composable function. You mark a function with @Composable and inside it you call other composables to describe the hierarchy. Text, Button, Column, Row and Image are the bread and butter you will reach for again and again. Think of a composable as a recipe: list the ingredients, describe how they combine, and Compose takes care of measuring, laying out and drawing them.

Modifiers are the chainable configuration objects you apply to composables. They control padding, size, background, click handling, and much more. Order matters in a modifier chain. Putting padding before a background colours only the content area, while swapping the order expands the background to include the padded region. This subtlety trips up newcomers from Melbourne and beyond, so it is worth experimenting in the preview pane.

Material 3 is the design system you will lean on for consistent theming. It provides color schemes, typography scales and shape definitions that align with modern Android aesthetics. Local apps such as the Australian Taxation Office's myTax or major bank clients from CommBank and NAB use Material principles, so adopting the same vocabulary will help if you ever audit those codebases.

State, hoisting and recomposition explained

State in Compose is any value that can change over time and affects what the UI renders. You declare state with the remember function, or rememberSaveable for values that survive configuration changes. When state changes, Compose marks the affected composables as needing recomposition and schedules a pass on the UI thread. Recomposition is incremental, so a small change in one corner of the screen does not force the whole tree to redraw.

Hoisting state means lifting it to a common ancestor so multiple children can read or write it. This pattern mirrors the lifting state up philosophy popular in React circles and is essential for building testable, reusable components. A practical example is a counter screen: the count lives in a parent composable, while the buttons receive callbacks to increment or decrement. Passing the setter down is what makes the pattern stateless from the child's perspective.

Side effects such as launching a coroutine, listening to a Flow, or animating a value are handled through dedicated APIs like LaunchedEffect, SideEffect and DisposableEffect. Triggering a side effect directly inside the composition body can lead to repeated executions that break your logic. Afterpay, the Sydney headquartered fintech, shares open source components showing clean effect handling.

Building a real screen and iterating on a device

With the fundamentals in place, build a small screen that pulls a list of items. Use a LazyColumn for scrolling performance, define a data class for the items, and hoist the list state into a ViewModel. Pair Compose with Hilt for dependency injection to swap a fake repository in development for a real one in production. Expose the list as a Flow so the UI can collect it within a LaunchedEffect block.

Run the app on a physical device if you can. Emulators are fine for quick checks, but nothing beats testing on a Pixel or a Samsung Galaxy to feel how animations and scrolling behave. If you are in Sydney, drop by the Google office in Pyrmont for occasional device lab events, or join the GDG meetups in your city to borrow hardware for an evening.

Once your screen works, add a preview annotation and refine the layout using the interactive preview pane. You can see your UI in light and dark themes, different font sizes, and various screen sizes. This helps when designing for Australia's mix of phones and foldables.

Helpful libraries to add early on

  • accompanist for Compose friendly permissions
  • coil-compose for async image loading
  • compose-navigation for fragment free routing
  • material-icons-extended for vector icons

Beginner mistakes worth avoiding

  • Forgetting to hoist state, blocking reuse and testing
  • Placing side effects in the body instead of LaunchedEffect
  • Ignoring modifier chain order, breaking padding or background
  • Overusing nested layouts when a LazyColumn would scroll better

Now is the perfect moment to open Android Studio and start typing. Pick a tiny feature from an app you love, perhaps a settings screen or a search bar, and recreate it from scratch using only Compose. Share your work in a local channel, attend a meetup in your nearest capital city, and read the source code of open source apps maintained by Australian teams.