The fastest guide of ViewBinding usage (Kotlin)

Sergey Shustikov
2 min readNov 27, 2020

--

No, water, not useless words. You know everything. Just code.

1. Setup

android {
//...
buildFeatures {
viewBinding = true
}
}

Then, rebuild the project to generate ViewBingins.

2. Where are my ViewBindings now?

Go to

<your_module_name>/build/generated/data_binding_base_class_source_out

Expand the folder to see your generated ViewBindings!

3. Usage

3.1 Usage in Activity

private lateinit var binding: ResultProfileBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ResultProfileBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
}

Then

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

3.2 Usage in Fragment

private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = ResultProfileBinding.inflate(inflater, container, false)
val view = binding.root
return view
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

Then use it in the same way as in Activity before.

3.2 Usage in ViewHolders

class BannersViewHolder(val binding: RvCategoryBannersBinding) : RecyclerView.ViewHolder(binding.root), BaseClickListener {

private val rvBanners: RecyclerView = binding.rvCategoryBanners

fun bind(viewModel: CategoryBannersViewModel) {
// do your stuff
}
}

and pass ViewBinding from Adapter :

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val binding = RvCategoryBannersBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BannersViewHolder(binding)
}

Note: You can play with bind method to achieve more cleaner memory management inside RecyclerView, but… it’s not related to this article.

4. Corner cases

4.1 <merge> layouts

Inside Fragment :

private var _binding: FragmentSettingsBinding? = null
private val binding get() = _binding!!

private var _debugMenuBinding: DebugInfoBinding? = null
private val debugMenuBinding get() = _debugMenuBinding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentSettingsBinding.inflate(inflater, container, false)
_debugMenuBinding = DebugMenuBinding.bind(binding.root)
return binding.root
}

If you have something like

<include layout="@layout/debug_menu" />

in your layout. For Activity do the same thing (DebugMenuBinding.bind(binding.root))

4.2 <include> layouts

private lateinit var binding: ActivitySelectAddressBindingoverride fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySelectAddressBinding.inflate(layoutInflater)
setContentView(binding.root)
}

Here we have another way to declare it

binding.bottomSheet.rvRestaurantListDialog.layoutManager = LinearLayoutManager(this)
binding.bottomSheet.rvRestaurantListDialog.adapter = rvAdapter

activity_select_address.xml :

<include android:id="@+id/bottom_sheet" layout="@layout/bottom_sheet_view" />

5. Okay. Let’s talk a bit

  1. Understand the difference between inflate and bind methods :
  • inflate — inflates the view by context and other options. This method use bind inside
  • bind — expecting to get the parent layout, that contains all views declared in this Binding. Be aware: if you’ll pass an incorrect view inside — you’ll get a ClassCastException.

2. As ViewBindings is a good mechanism to make your code more null-safety (with other advantages), however, you can notice that ViewBindings usage produce a boilerplate code. I strongly recommend you to look at ViewBindings + Kotlin delegates tutorial.

3. Feel free to send me any advice or suggestion to improve this article.

--

--