Achieving Interface segregation in Android using Kotlin extension and inline functions

Vinay John
3 min readMar 13, 2022

--

SOLID Principles

Robert C Martin famously known as “Uncle Bob” defined Solid Principles which are guidelines to follow when building software so that it is easier to scale and maintain. SOLID is an acronym and each letter denotes an object-oriented design (OOD) principle. In this article we are going to focus on letter “I” from SOLID which explains the idea of Interface segregation principle.

So what does Interface segregation principle say :

“The clients shouldn’t be forced to implement the methods that they do not use”.

Let us take an example of the TextWatcher interface in Android. This interface is widely used in development when we want to receive callbacks when a user changes the text in any TextView Inheriting View (for eg : EditText). We can add a TextWatcher interface to an EditText using addTextChangedListener Function which is added in the TextView class.

Example Scenario : Need to show a Toast message with the current text whenever user enters a character into EditText.

To achieve this we need to attach the TextWatcher interface to an EditText using the addTextChangedListener function. Here, we are forced to implement all 3 functions of the TextWatcher interface.

The Code will look like this :

binding.editText.addTextChangedListener(object: TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence?, p1: Int, p2: Int, p3: Int) {
//NO OP
}

override fun onTextChanged(charSequence: CharSequence?, p1: Int, p2: Int, p3: Int) {
showToast(charSequence.toString())
}

override fun afterTextChanged(charSequence: Editable?) {
//NO OP
}

})

Here, we only require onTextChanged function for showing the functionality. We don’t require beforeTextChanged and afterTextChanged functions and implementing this is a violation to Interface segregation principle.

Now the question arise — How can we segregate the functions in the TextWatcher interface and use only onTextChanged function.

With the help of powerful Extension function in Kotlin and the use of inline function which enhances the efficiency of the Kotlin code when using Higher Order Functions, let us optimise the code to satisfy Interface segregation principle.

Let’s start with creating a new Extension function onTextChanged on the EditText class. This will add the function to EditText class and we can use it wherever we need the functionality.

Please check the below Code :

inline fun EditText.onTextChange(crossinline listener: (String) -> Unit) {
this.addTextChangedListener(object: TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence?, p1: Int, p2: Int, p3: Int) {
//NO OP
}

override fun onTextChanged(charSequence: CharSequence?, p1: Int, p2: Int, p3: Int) {
listener(charSequence.toString())
}

override fun afterTextChanged(p0: Editable?) {
//NO OP
}

})
}

Here, we are adding a lambda function listener as a parameter to our onTextChange Extension function. The function listener takes String as an argument. Whenever the callback function onTextChanged in TextWatcher is called we will invoke the function listener and pass a string argument to it.

This extension function can be used with the EditText like :

binding.editText.onTextChange {
showToast(it)
}

Inside onTextChange you will receive the String which is passed from the onTextChanged function of the TextWatcher interface and we can add our functionality of showing a Toast.

inline : The use of inline function enhances the performance of higher order function. The inline function tells the compiler to copy parameters and functions to the call site.

crossinline : crossinline keyword is added to avoid non-local returns. ie, if we have added the return inside the lambdas, it will allow the non-local returns and left the code below that. To avoid this we are using crossinline keyword before the lambda function listener.

We can use the same approach when we are trying to implement interfaces which contain a lot of functions and we need to use only one/two at a time. Using this approach will make the code more concise and efficient.

Thanks for Reading!!! Happy Coding!!!

Github Link : https://github.com/vinay4791/SolidPrinciples

--

--