Jetpack Compose Intro
๐๏ธ Jetpack Compose Intro
๐งฑ Composable Functions
A @Composable function describes a piece of UI โ calling Text(...) doesn't create and configure a View object the way binding.textView.text = "..." did in Course 1; it declares "there should be text here, with this content." Composables are Kotlin functions in every technical sense โ they take parameters, can call other composables, and can be as small or as large as any function โ but by convention they're named with a capital letter, like a class, to visually mark them as UI-producing.
Column and Row are Compose's layout composables โ the direct replacements for Course 1's LinearLayout (vertical/horizontal orientation), just as Kotlin function calls instead of XML tags. Modifier is Compose's mechanism for spacing, sizing, and other per-element styling โ the composable-world equivalent of an XML View's layout_* attributes, but chainable: Modifier.padding(16.dp).fillMaxWidth().
๐ State & Recomposition โ The Core Idea
A composable function re-runs โ recomposes โ automatically whenever the state it reads changes, redrawing only what actually needs to change:
remember { mutableStateOf(0) } creates a piece of state that survives recomposition (though not, by default, an Activity being recreated โ that's rememberSaveable, a small variant covered later). by is Kotlin Intermediate Chapter 4's property delegation again โ mutableStateOf provides getValue/setValue, letting count be read and written like a plain var, while every read is secretly tracked by Compose.
When count++ runs inside the button's onClick, Compose doesn't manually push a new value into the Text โ it re-runs (recomposes) exactly the composable functions that read count, because it tracked that read the last time they ran. Text(text = "Count: $count") reads count, so it recomposes; if Counter had other composables that never touched count, those would be skipped entirely โ an automatic, fine-grained optimization with no equivalent manual work required.
Compose vs XML/View System (Course 1)
| XML + Views (Course 1) | Jetpack Compose | |
|---|---|---|
| UI defined in | Separate XML files | Kotlin functions |
| Updating the UI | binding.textView.text = "..." (imperative mutation) | Change state; recomposition updates the UI automatically |
| Finding a View | findViewById / view binding | N/A โ no View objects to "find" |
| Reusability | A custom View class, or a <include> layout | Just a function โ call it anywhere |
Compose vs React โ A Very Similar Shape
| React | Jetpack Compose | |
|---|---|---|
| Component unit | A function component | A @Composable function |
| Local state | useState() | remember { mutableStateOf(...) } |
| Re-render trigger | State change โ re-render | State change โ recomposition |
| Optimization | Virtual DOM diffing | Skips composables whose inputs didn't change |
If React (from the JavaScript courses) feels familiar, that's not a coincidence โ both are declarative, state-driven UI systems built around the same core insight: describe what the UI should look like given the current state, and let the framework figure out the minimal work to get there, rather than hand-writing the update steps yourself.
๐๏ธ @Preview โ Seeing UI Without Running the App
A @Preview-annotated composable renders directly inside Android Studio's editor, without building, installing, or launching anything on an emulator:
This is a genuinely fast feedback loop compared to Course 1's edit-build-run cycle for checking a layout change โ a dedicated, no-argument preview function calling the real composable with sample data shows up right in the code editor's split view, updating live as the code changes.
๐๏ธ Wiring Compose Into an Activity
Note two changes from Course 1: the base class is ComponentActivity, not AppCompatActivity, and setContent { } replaces setContentView(R.layout.activity_main) โ there's no XML layout file at all for a Compose screen. Everything else from Course 1's Activity lifecycle (Chapter 2) still applies unchanged; Compose is a different way of building the content of a screen, not a different kind of Activity.
๐ป Coding Challenges
Challenge 1: A Composable with Parameters
Write a composable fun ProductCard(name: String, price: Double) using a Column to display both values as separate Text elements, and a @Preview function calling it with sample data. Wire it into MainActivity via setContent { }.
Goal: Practice a basic parameterized composable and the Preview workflow.
Challenge 2: State and Recomposition
Write a composable Counter() with a remembered mutableStateOf Int starting at 0, a Text showing the current value, and two Buttons ("+" and "-") that increment/decrement it. Confirm the displayed count updates correctly when either button is tapped.
Goal: Practice remember/mutableStateOf and see recomposition happen for real.
Challenge 3: Composing Composables Together
Using Challenge 1's ProductCard, write a composable ProductList() that calls ProductCard three times (with different sample data) inside a Column, separated by some vertical spacing (Modifier or a Spacer). Add a @Preview for ProductList.
Goal: Practice composing smaller composables into a larger screen, the way small functions combine into larger ones.
Many real, existing Android codebases still use the View system from Course 1, and Compose screens frequently need to interoperate with legacy View-based code (via AndroidView or ComposeView) โ understanding both isn't redundant, it's genuinely necessary for working on real production Android apps today. This course focuses on Compose going forward because it's what new code is built with, not because Course 1 was a detour.
๐ฏ What's Next
Next chapter: ViewModel & State Management โ ViewModel lifecycle, LiveData, StateFlow, and UI state patterns.