The fastest guide of ViewBinding usage (Kotlin)
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
- Understand the difference between
inflate
andbind
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.