Anko — making android developers’ lives easy

Prem Suman
5 min readJun 26, 2019

--

Image referenced from here

As a developer, we thrive to write clean, descriptive and efficient code that pertains to a particular practice. In addition to that, we do not want to leave any chances to make our code shorter, after all, Deleting code is important than writing it!

As a developer myself, I am constantly looking to improve upon my code, make it more efficient, reduce the number of lines, remove duplicate code, etc. You can say I kind of have an OCD towards that.
For instance, when I started Android development, the Java code used to be full of findViewById() calls. Then I came across the ButterKnife library, which reduced the requirement for the extra findViewById() calls, but developers need more! I still had to declare the member variables in the class, so if I wanted to reference 20 views in my class, there would be 20 lines extra (and depending on the formatting of annotations, it can also be 40!).

One more example could be when we need to setOnTextChangedListener, we had to do an ugly concoction of overridden functions inside a new anonymous class that we didn’t really need to use, which resulted in more code. An alternative to this was to create an abstract class and then implementing the required functions, but then again, EXTRA CODE!

Then as I migrated to kotlin for android development, the amount of code reduced a lot, and the coed was more flexible, cohesive and descriptive. Lambdas helped in some listeners.

Enter Anko!

Then I came across the Anko library (Github link), it is purely written in Kotlin and maintained by JetBrains. Its purpose is to speed up android development by using the power and capabilities of Kotlin, thus making it more convenient for us.

If you look closely, you’ll see Anko = (An)droid + (ko)tlin

Anko has four main modules:

  • Anko Commons
  • Anko Layouts
  • Anko SQLite
  • Anko Coroutines

The Commons module has a number of helper/utility functions and features. The layouts module of the library can help you can create UI from Kotlin code with a feature called Anko DSL. The SQLite module of the library makes interacting with SQLite databases simpler. And last but not least, Anko provides a few helper functions for one of Kotlin’s biggest feature: Kotlin coroutines.

In this article, I am going to focus on the Anko Commons module.

Anko Commons

OnClickListeners

The View.setOnClickListener method is used everywhere in Android projects so it would be nice if we could make it more concise.
The longest form we can define a click handler in Kotlin:

someView.setOnClickListener(object : View.OnClickListener{
override fun onClick(view: View) {
//Stuff
}
}

But using Anko, we can just do

someView.onClick { /*Stuff*/ }

OnTextChangedListeners

The conventional way to define text watchers:

someView.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
// Stuff
}

override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
// Stuff
}

override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
// Stuff
}
})

Seems like a handful right? Especially when we just have to use one of the functions. Anko takes care of that:

someView.textChangedListener { 
beforeTextChanged { charSequence, start, before, after ->
/*Stuff*/
}

onTextChanged { charSequence, start, before, count ->
/*Stuff*/
}

afterTextChanged { editable ->
/*Stuff*/
}
}

Looks cleaner right? But wait there’s more, the good thing about this is all those overridden functions (beforeTextChanged { … }, onTextChanged { … } and afterTextChanged { … }) are optional, that means it will work perfectly fine when you even do this:

someView.textChangedListener { 
onTextChanged { charSequence, start, before, count ->
/*Stuff*/
}
}

Intents

One of the first things we learn in android development is Intents:

val intent = Intent(this, MainActivity::class.java)
intent.putExtra(ID, 5)
intent.putExtra(NAME, "John")
startActivity(intent)

Here’s how Anko simplifies it and makes it more readable:

startActivity(intentFor<MainActivity>(ID to 5, NAME to "John")

Anko also has a few helper functions for common use cases regarding Intents like opening a link, making a call, email, etc.:

// open a link
browse("https://some-website.com")
// share some text
share("share", "subject")
// send email
email("email@example.com", "Subject", "Body")
// make a call
makeCall("+123456789")
// send a text message
sendSMS("+123456789", "Message body")

Alert Dialogs

We all know what goes in creating an AlertDialog conventionally:

val builder = AlertDialog.Builder(this)
builder.setTitle("Title") builder.setMessage("Message")
builder.setPositiveButton("OK") { dialog, which ->
toast("Yay!")
}
builder.setNegativeButton("Cancel") { dialog, which ->
toast("Nay!")
}
builder.show()

Using Anko, it is more simplified and flexible:

alert("Message", "Title") {
// add custom view (optional)
customView { editText() } /* or use customView(view) */
yesButton { toast("YAY!") } /*button with text "YES"*/
noButton { toast("NAY!") } /*button with text "NO"
}.show()
// or alternatively, use buttons with custom text:
alert("Message", "Title") {
positiveButton("OK") { toast("Yay!") }
negativeButton("Cancel") { toast("NAY!") }
}.show()

Conversion of PX, DP, or SP?

Code size matters, also when doing dpi-maths programatically.

The old, complicated way:

val dpAsPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f, getResources().getDisplayMetrics())

The dead simple new way:

val dpAsPx = dip(10)// to get text sizes
sp(14)

Toasts and Snackbars

The Toast and Snackbar could also be better. Did you ever forget to call .show() after the function calls, and then debug it for half an hour why it's not showing? No? Maybe it's just me.

// for toasts
toast("message")
// for snackbars
longSnackbar(contentView, "This is a snack!")

API level issues

When we come across the code where we have to add a check that the code should only run for a specific API level, or onwards, the conventional :

if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
/*Stuff*/
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
/*stuff*/
}

And using Anko, it gets more readable:

doIfSdk(Build.VERSION_CODES.LOLLIPOP) {
/*Stuff*/
}
doFromSdk(Build.VERSION_CODES.LOLLIPOP) {
/*Stuff*/
}

MultiThreading

Handling multiple threads is not easy, but it’s a pretty common pattern in mobile development. Most of the time we want to offload work from the UI thread. The way to do it with Anko is pretty straightforward and concise.

doAsync {
//IO task or other computation with high cpu load
uiThread {
// get the result on UI thread
}
}

You can find more on the usages of doAsync { } and how it can efficiently replace AsyncTask here.

And last, but not the least,

Goodbye findViewById()

There is a new plugin called Kotlin Android Extensions Gradle plugin, which can help you get rid of all the hated findViewById() calls and casting Views by introducing one extra line to your module’s Gradle script:

apply plugin: 'kotlin-android-extensions'

Now you can just reference views from your XML files with their IDs.

// activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<EditText
android:id="@+id/some_EditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Write something"/>
<Button
android:id="@+id/some_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="OK"/>
</LinearLayout>
// MainActivity.kt
import kotlinx.android.synthetic.main.activity_main.*
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
some_button.onClick { /*Stuff*/ } some_textView.textChangedListener {
onTextChanged { charSequence, start, before, count ->
/*Stuff*/
}
}

}

More information on Anko, and how to add it to your project on Then I came across the Anko’s website and Github page.

--

--

Prem Suman
Prem Suman

Written by Prem Suman

Senior Android dev, tech enthusiast, loves to learn new things

No responses yet