This guide is written for Android developers who have used XML + View system and want to deeply understand Jetpack Compose, why it exists, and how it simplifies Android UI development.
Before Jetpack Compose, Android UI was built using:
- XML layouts
- View hierarchy
- Adapters
- ViewBinding / DataBinding
- Manual state updates
- Too much boilerplate
- UI logic split across XML + Activity
- Hard to manage state
- RecyclerView adapters are complex
- Animations are difficult
- Performance issues due to deep view hierarchies
| XML (Old Way) | Jetpack Compose (New Way) |
|---|---|
| Imperative UI | Declarative UI |
| Modify views manually | UI reacts to state |
| XML + Kotlin | Kotlin only |
| View hierarchy | Function calls |
findViewById() |
No view lookup |
| RecyclerView | LazyColumn |
Compose UI = function(state)
XML Approach
layout.xml
<TextView
android:id="@+id/tvHello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World"/>Activity
val textView = findViewById<TextView>(R.id.tvHello)
textView.text = "Hello Android"- UI defined in XML
- Logic in Activity
- Manual updates required
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name")
}
- UI + logic in one place
- No XML
- No view references
- Automatically updates when data changes
XML Way (Old)
button.setOnClickListener {
counter++
textView.text = counter.toString()
}
- You manually update the UI
- Easy to forget updates
- Hard to manage complex states
Compose Way
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Count: $count")
}
}
- UI automatically updates
- State-driven
- Less error-prone
XML Layout
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView ... />
<Button ... />
</LinearLayout>
Compose Layout
Column {
Text("Welcome")
Button(onClick = {}) {
Text("Continue")
}
}
- Cleaner
- Less nesting
- Readable
XML Styling
<TextView
android:padding="16dp"
android:background="@color/blue"
android:textColor="@color/white"/>
Compose Styling (Modifiers)
Text(
text = "Hello",
modifier = Modifier
.padding(16.dp)
.background(Color.Blue),
color = Color.White
)
- Everything is Kotlin
- Modifier order matters
- Extremely flexible
XML + RecyclerView (Old Way) You need:
- RecyclerView
- Adapter
- ViewHolder
- XML row layout
class UserAdapter : RecyclerView.Adapter<UserViewHolder>() { ... }
Compose LazyColumn
LazyColumn {
items(users) { user ->
Text(user.name)
}
}
- No adapter
- No ViewHolder
- Less code
- More readable
XML Navigation
- nav_graph.xml
- Fragment transactions
- BackStack handling
Compose Navigation
NavHost(navController, startDestination = "home") {
composable("home") { HomeScreen() }
composable("profile") { ProfileScreen() }
}
- Everything in Kotlin
- Easier to understand
- Less bugs
XML Animation
- animation.xml
- Animator
- Listeners
- Complex
- Hard to debug
Compose Animation
AnimatedVisibility(visible = isVisible) {
Text("Hello Animation")
}
- Declarative
- State-based
- Simple
| XML + Views | Jetpack Compose |
|---|---|
| ViewBinding | No binding |
| LiveData | StateFlow / State |
| Manual UI update | Auto recomposition |
| Fragment heavy | Function based |