The view binding function can be enabled by module. To enable view binding in a module, add the viewBinding element to its build.gradle file, as shown in the following example
android { viewBinding { enabled = true } }
If you want to ignore a layout file when generating binding classes, add the tools:viewBindingIgnore="true" attribute to the root view of the corresponding layout file
<LinearLayout ... tools:viewBindingIgnore="true" > ... </LinearLayout>
After the view Binding function is enabled for a module, the system will generate a Binding class for each XML layout file contained in the module. Each Binding class contains a reference to the root view and all views with ID s. The system will generate the name of the Binding class by converting the name of the XML file to hump case and adding the word "Binding" at the end
Suppose the name of a layout file is result_profile.xml
<LinearLayout> <TextView android:id="@+id/name" /> <ImageView android:cropToPadding="true" /> <Button android:id="@+id/button" android:background="@drawable/rounded_button" /> </LinearLayout>
The name of the generated binding class is ResultProfileBinding. This class has two fields: a TextView named name and a Button named Button. The ImageView in the layout has no ID, so there is no reference to it in the binding class
Each binding class also contains a getRoot() method to provide a direct reference to the root view of the corresponding layout file. In this example, the getRoot() method in the ResultProfileBinding class returns the LinearLayout root view
Use view binding 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) } binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
Using view binding 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 }
Difference from findViewById
View binding has some significant advantages over using findViewById
- Null pointer security: since view binding creates a direct reference to the view, there is no risk of null pointer exception due to invalid view ID. In addition, if the view appears only in some configurations of the layout, the fields in the binding class that contain its references are marked with @ Nullable
- Type safe: fields in each binding class have types that match the views they reference in the XML file. This means that there is no risk of class conversion exceptions
ViewBinding vs Kotlin Android Extensions with synthetic views
Both are type safe and null pointer safe, but KAE's import and setContentView are separated, resulting in null pointer problems