· 4 min read

Unleash functional power on Android (I): Kotlin lambdas

The functional programming can be a really powerful tool when used properly, and though Java 8 includes some functional tools, as you can imagine Android Developers won’t be able to use it very soon (or even never). So many alternative languages are starting to emerge to solve this problem.

Functional Programming in modern languages

Functional programming relies on functions and immutability, so that a call to a function always returns the same result. As usual, the perfection is in the middle point, so most modern languages, such as Kotlin or Scala, combine procedural and functional programming, providing the most powerful ideas of both in a single language. There are problems that are better solved using functional programming, and some others that are more direct when sticking to procedural programming.

Lambdas in Android using Kotlin

A lambda expression is a simple way to define an anonymous function. Lambdas are very useful because they prevent us from having to write the specification of the function in an abstract class or interface, and then the implementation of the class. In Kotlin, we can use a function as a parameter in another function. For example, a function that needs a callback can be simplified to this:

fun runAsync(callback: () -> Unit) { 
    ... 
    callback() 
}

And the usage is quite straightforward. After some transformations (that we’ll see later), a call to this function can be simplified as:

runAsync { toast("Finished") }

Another cool thing about Kotlin is that it lets us write interfaces with a single function as if they were a lambda, so we can hugely simplify our code. It’s easier to see in an example. Imagine we want to write a typical setOnClickListener() from a view.

The code for the interface in Java would be something like this:

public interface OnClickListener { 
    void onClick(View v); 
}

Then we need to write an anonymous class that implements this interface:

view.setOnClickListener(new OnClickListener() { 
    @Override 
    public void onClick(View v) { 
        Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show(); 
    } 
});

This would be the transformation of the code into Kotlin (using Anko toast function):

view.setOnClickListener(object : OnClickListener { 
    override fun onClick(v: View) { 
        toast("Click") 
    } 
})

As I mentioned before, Kotlin allows some optimizations over Java libraries, and any function that receives an interface with a single function can be substituted by the function. It will work as if we had defined setOnClickListener() like this:

fun setOnClickListener(listener: (View) -> Unit)

A lambda expression is defined by the parameters of the function to the left of the arrow (surrounded by parentheses), and the return value to the right. In this case, we get a View and return Unit (nothing). So with this in mind, we can simplify the previous code a little:

view.setOnClickListener({ view -> toast("Click") })

Nice difference! While defining a function, we must use brackets and specify the parameter values to the left of the arrow and the code the function will execute to the right. We can even get rid of the left part if the parameters are not being used:

view.setOnClickListener({ toast("Click") })

If the function is the last one in the parameters of the function, we can move it out of the parentheses:

view.setOnClickListener() { toast("Click") }

And, finally, if the function is the only parameter, we can get rid of the parentheses:

view.setOnClickListener { toast("Click") }

More than five times smaller than the original code in Java, and much easier to understand what it is doing. Really impressive. Anko gives us a simplified (basically in name) version, which consists of an extension function implemented the way I showed you before:

view.onClick { toast("Click") }

Extending the language

Thanks to these transformations, we can create our own builders and code blocks. Kotlin standard library provides some interesting functions such as with. A simpler implementation would be:

inline fun <T> with(t: T, body: T.() -> Unit) { 
    t.body() 
}

This function gets an object of type T and a function that will be used as an extension function. The implementation just takes the object and lets it execute the function. As the second parameter of the function is another function, it can be brought out of the parentheses, so we can create a block of code where we can use this and the public properties and functions of the object directly:

with(forecast) { 
    Picasso.with(itemView.ctx)
        .load(iconUrl)
        .into(iconView) 
    dateView.text = date 
    descriptionView.text = description 
    maxTemperatureView.text = "${high.toString()}º" 
    minTemperatureView.text = "${low.toString()}º" 
    itemView.onClick { itemClick(forecast) } 
}

Conclusion

The power of lambdas is only tied to our imagination. Taking out the most of them requires practice if you’re not used to functional programming, but it totally pays off. If you want to keep learning more stuff about lambdas and Kotlin, I tell a lot more in the book I’m writing.

    Share:
    Back to Blog