Boost Your Android Code Quality With BaseFragment

Fragments play a crucial role in Android development, enabling modular and reusable UI components within an application. However, working with Fragments can sometimes be repetitive and time-consuming. But fear not! BaseFragment is here to help with that.

Boost Your Android Code Quality With BaseFragment
Photo by Sigmund / Unsplash

Fragments play a crucial role in Android development, enabling modular and reusable UI components within an application. However, working with Fragments can sometimes be repetitive and time-consuming, especially when it comes to implementing data binding and ViewModel. But fear not! There's a powerful tool at your disposal to streamline and enhance your Fragment development experience: the BaseFragment.

What we will be diving into?

In this blog post, we will explore the importance of using BaseFragment in your Android projects and how it can significantly improve code quality. We'll specifically delve into the repetitive tasks of implementing view binding and ViewModel in Fragments and how BaseFragment can simplify and optimize these processes. So, get ready to take your Android development skills to the next level and discover the benefits of leveraging BaseFragment in your code. Let's dive in!


We will divide the process of creating the base fragment class into 4 simple steps:

  1. Writing the BaseFragment class with appropriate parameters:

Now, when I say appropriate parameters, I mean the parameters that we will be passing through the actual Fragment, which will inherit the BaseFragment. You may ask why is such a simple process a step. Let me tell you – when I was first learning how to implement BaseFragment, I came across many sources that claimed to have the proper solution but did not follow up with them. Anyway, the code goes something like this:

open class BaseFragment<VBinding : ViewBinding>(
    private val inflateMethod: (LayoutInflater, ViewGroup?, Boolean) -> VBinding
) : Fragment() {

}

Now there are a few things you need to understand here. First, what does the open  keyword specify here? An open class allows other classes to inherit from it and override its methods. If you intend for other fragments to inherit from BaseFragment and potentially modify their behavior, you can make it an open class.

Now as a parameter, we pass inflateMethod, which specifies three things, – LayoutInflater, ViewGroup, and AttachToParent which is of type Boolean, and the return type is specified as the type ViewBinding denoted by VBinding.

Finally the BaseFragment inherits the Fragment() class to act as a common pass-through for all other fragments.

2. Declaring and Initializing ViewBinding with NullSafety

open class BaseFragment<VBinding : ViewBinding>(
    private val inflateMethod: (LayoutInflater, ViewGroup?, Boolean) -> VBinding
) : Fragment() {

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

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

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

We define the binding here just as instructed in the Android Documentation. We create the onCreateView and onDestroyView functions and override them accordingly.

As an added step, you can also check whether _binding is null and throw an IllegalStateException with a custom message to both the user and the developer.

3. Decrease Boilerplate code in other fragments that inherit BaseFragment

In order to do this, we define an open function initialize(), and override it using the respective binding associated with the fragment it is overridden in.

open class BaseFragment<VBinding : ViewBinding>(
    private val inflateMethod: (LayoutInflater, ViewGroup?, Boolean) -> VBinding
) : Fragment() {

    private var _binding: VBinding? = null
    val binding: VBinding get() = _binding!!
    
	//open function initailze() to be overriden in other fragments
    open fun VBinding.initialize(){}

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = inflateMethod.invoke(inflater, container, false)

		//accessing the open function in onCreateView
        binding.initialize()

        return binding.root

    }

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

4. Passing respective bindings in Fragments and accessing ViewBinding after that

Consider there is a fragment named TestFragment.kt and this is how you will write the code to access BaseFragment()

class TestFragment : BaseFragment<FragmentTestBinding>(
    FragmentTestBinding::inflate
) {

}

Finally, you can call to override the initiaze() to do any task required instead of using the onCreateView() here, since the initialize() function is already initialized inside of the onCreateView() of the BaseFragment().

class TestFragment : BaseFragment<FragmentTestBinding>(
    FragmentTestBinding::inflate
) {

	override fun FragmentTestBinding.initialize() {
    	networkCalls()
        clickListeners()
        attachObservers()
      	//do tasks here
    }

}

In conclusion, incorporating BaseFragment into your Android development workflow can greatly enhance code quality and productivity. By leveraging the power of BaseFragment, you can streamline repetitive tasks such as implementing data binding and ViewModel in Fragments.

Using BaseFragment allows you to consolidate common functionality, reducing code duplication and promoting a modular and maintainable codebase. With data binding, you can effortlessly bind UI elements to your data models, making your code more concise and readable. Additionally, the integration of ViewModel provides a robust and efficient way to handle data logic and state management within Fragments.

By adopting BaseFragment as a fundamental component in your Android projects, you'll experience numerous benefits. It simplifies the development process, boosts code reusability, and improves overall code quality. Moreover, it helps to enforce best practices and facilitates collaboration among team members.

So, don't hesitate to embrace BaseFragment and unlock the potential to build high-quality Android applications with ease. With its ability to reduce boilerplate code and enhance development efficiency, BaseFragment empowers you to focus more on implementing unique features and delivering exceptional user experiences.

Start using BaseFragment in your projects today, and witness the remarkable transformation it brings to your Android development journey. Happy coding!