🎨 UI – Views & Layouts · Lesson 12
View Binding
The problem with findViewById
Kotlin
// ❌ findViewById – easy to use the wrong id or wrong type val tvMessage = findViewById<TextView>(R.id.tvMessage) val btnHello = findViewById<Button>(R.id.btnHelo) // typo → crash only at runtime
findViewById
- One line per view
- Wrong id → crash at runtime
- Wrong type cast → crash
- Can return null
View Binding
- All views ready in one object
- Wrong id → compile error
- Correct type automatically
- Null-safe
Step 1: Enable View Binding
Kotlin DSL – app/build.gradle.kts
// app/build.gradle.kts
android {
// ...
buildFeatures {
viewBinding = true
}
}
// then: File → Sync Project with Gradle FilesHow names are generated
| Layout file | Binding class |
|---|---|
| activity_main.xml | ActivityMainBinding |
| fragment_notes.xml | FragmentNotesBinding |
| item_note.xml | ItemNoteBinding |
| View id | Property |
|---|---|
| @+id/tvMessage | binding.tvMessage |
| @+id/btn_save | binding.btnSave (snake_case → camelCase) |
| (root view) | binding.root |
Step 2: Use it in an Activity
Kotlin – MainActivity.kt
package com.example.helloapp
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.helloapp.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var count = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) // 1. inflate
setContentView(binding.root) // 2. show its root view
binding.btnHello.setOnClickListener { // 3. use ids as properties
count++
binding.tvMessage.text = "Namaste! You clicked $count times"
}
}
}Using it in a Fragment
Kotlin – NotesFragment.kt
class NotesFragment : Fragment() {
private var _binding: FragmentNotesBinding? = null
private val binding get() = _binding!! // valid only between onCreateView and onDestroyView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentNotesBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.tvTitle.text = "My notes"
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null // avoid memory leaks
}
}Using it in a RecyclerView adapter
Kotlin – NoteAdapter.kt
class NoteAdapter(private val items: List<String>) :
RecyclerView.Adapter<NoteAdapter.VH>() {
class VH(val binding: ItemNoteBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
VH(ItemNoteBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun onBindViewHolder(holder: VH, position: Int) {
holder.binding.tvTitle.text = items[position]
}
override fun getItemCount() = items.size
}Included layouts and ignoring a layout
XML + Kotlin
<!-- activity_main.xml -->
<include
android:id="@+id/header"
layout="@layout/layout_header" />
// Kotlin – the include becomes a nested binding
binding.header.tvHeaderTitle.text = "Dashboard"
<!-- to skip generating a binding class for a layout -->
<LinearLayout xmlns:tools="http://schemas.android.com/tools"
tools:viewBindingIgnore="true" />Common mistakes
- Calling
setContentView(R.layout.activity_main)AND inflating the binding → two copies; your listeners attach to the invisible one. UsesetContentView(binding.root). - Forgetting Gradle sync → "Unresolved reference: databinding".
- Using
bindingin a fragment after onDestroyView (e.g. in a late callback) → crash; check_binding != null.
Summary
- Enable
viewBinding = true; each layout gets anXxxBindingclass. - Activity:
inflate(layoutInflater)+setContentView(binding.root). - Fragment:
_bindingnullable, cleared inonDestroyView.
✅ Practice
Convert your BMI calculator from findViewById to View Binding. Count how many lines you removed.
Frequently Asked Questions
Is View Binding the same as Data Binding?
No. View Binding only generates references to views. Data Binding also lets you write expressions in XML. View Binding is simpler and faster to build, and is what most projects use.
Why do Fragments use _binding and binding?
A fragment can outlive its view. Setting _binding = null in onDestroyView releases the old views, preventing memory leaks; binding is a non-null getter used in between.
Does View Binding slow down my app?
No. The binding class is generated at build time and inflates the layout once — it is as fast as findViewById.
