CodeNewbie Community 🌱

Cover image for Android Fragment View Binding with Kotlin explained
Tristan
Tristan

Posted on

Android Fragment View Binding with Kotlin explained

Introduction

  • This series is not going to be in any particular order, so feel free to read whatever blog post you want. Anytime I find something that I think could use a blog post, I will write one and put it here

References

What we are going to talk about

  • Ok so I wanted to talk a little about View Binding and more specifically, explain the syntax of the code below:
private var _binding:FragmentMainBinding? = null;
private val binding get() = _binding!!;

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

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

Enter fullscreen mode Exit fullscreen mode
  • While the official documentation does do a good job of getting you up and running, it skips over some of the Kotlin syntax and if you are new to Kotlin, this can be confusing.
  • So we are going to quite literally go line by line and explain what is going on.

private var _binding:FragmentMainBinding? = null;

  • Before we can truly dive into what this statement is saying we need to talk about a few things. One of those things is understanding what a property is.

Property

  • So if you are familiar with object oriented programming(don't worry if you are not), the whole idea of a class is to encapsulate (store) data and code that works on that data into a single entity.
    • Now in a language like Java this is done through defining a field to hold the data and then defining accessor methods (getters and setters) to access the data. In Java it would look something like this:
//field
private int data; 

//accessor methods
public void setData(int data){
  this.data = data;
}
public int getData(){
   return this.data;
}
Enter fullscreen mode Exit fullscreen mode
  • The combination of a field and the accessor methods creates what we call a property. So anything you read property think field plus accessor methods.
  • There are actually two types of properties. readable properties, which means we can only read their values and not change them. Writeable properties, which means we can read and change the values.

  • Kotlin does things a little differently, there are no individual fields and accessor methods, only properties. I know that might sound a little weird but just hear me out. When we declare a variable with either val(immutable) or var(mutable) we are actually defining a readable property and a writable property. Under the hood Kotlin will automatically create the necessary field and accessor method. So when we write:
    private var _binding , we are creating a private writable property called _binding.

FragmentMainBinding? = null;

  • Now that we have explained the first half, lets explain the second half. As stated in the official View Binding documentation, HERE, if view binding is enabled for a module, a binding class is generated for each XML layout file that the module contains. Each binding class contains references to the root view and all views that have an ID. The FragmentMainBinding class is created from an XML layout file I have called fragment_main. But what is the ? doing? To talk about that, we need to talk about null safety.

Null safety

  • Kotlin's type system distinguishes between references that can hold null(nullable references) and those that cannot(non-null references). To distinguish between the null references and the non-null reference, we use the ? operator. If stated after a reference, like in our situation, it means that this property can hold a null value. Notice the error that appears when you delete the ? operator.
  • While we are on the topic of null safety lets talk about the not null assertion operator, which is the double exclamation mark !!. This operator is done to convert any values to a non-null type or throw an exception if the value is null. So if !! follows a reference it means the value will be non null or if it is null then a null pointer exception will be thrown.

  • That was a rather long winded solution, but we know know that private var _binding:FragmentMainBinding? = null; is creating a private writable property called _binding that can hold a type of FragmentMainBinding or null.

  • Next line line!!!

private val binding get() = _binding!!;

  • Now from our property discussion we know that we are creating a readable property called binding. The thing about readable properties is that they only generate one accessor method, the getter. The get() comes into play with defining a custom accessor method. So with get() = _binding!! we are actually defining a custom accessor getter method that will get the value of _binding!!. If this is hard to understand, let me try to present an alternative syntax:
//documentation given syntax
private val binding get() = _binding!!;
//alternative syntax
private val binding:FragmentMainBinding get(){  
         return _binding!!
};

Enter fullscreen mode Exit fullscreen mode
  • Both statements in the code above are equivalent to each other. However, I believe that the alternative syntax paints a clearer picture about us defining a custom accessor method for the binding property.

  • So the code, private val binding get() = _binding!! is telling us that we are creating a private readable property called binding and then creating a custom getter method which will allow us to access the value of _binding each time the binding variable is accessed.

  • Next line!!!!! Or in this case next method

onCreateView()

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

Enter fullscreen mode Exit fullscreen mode
  • So the first thing here is to point out the obvious of override fun. This is just us overriding the function called onCreateView that is inherited from the Fragment class.

  • Now we get to talk about the the actual onCreateView() method and this can get a little confusing, so buckle up. We all know that Fragments are not standalone entities, they must be hosted by an Activity. This means that the life and death of a Fragment is ultimately controlled by the Activity's lifecycle, read more about the Activity life cycle HERE. Once the Activity enters it's CREATED state, it will do a number of things such as instantiate the Fragment, add it to the Fragment Manager and attach it to the host Activity. Once these steps are over the Fragment enters it's own CREATED state. Read more about the Fragment lifecycle HERE. It is in this state that our onCreateView() method is called and assuming that we provided our Fragment with a non-null view(via view binding) the view returned from this method will be the one shown to the user.

onDestroyView()

  • This method will get called when the host Activity is in the DESTROYED state. There are a number of reasons an Activity might be in the DESTROYED state, such as, the user pressing the back button or a memory constraint by the system. For us we are doing one thing inside this method and that is _binding = null, which is us manually setting our View Binding object to null. This is done to prevent memory leaks and to ensure that each call of onCreateView() returns a fresh and newly updated View.

Conclusion

  • Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.

Top comments (0)