Anko Commons Tutorial

See how to improve the readability and conciseness of your Android Kotlin code for Intents, Dialogs and more using the Anko library from JetBrains. By Arturo Mejia.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Using Anko Commons

Let’s do a deep dive to see what Anko Commons can do for you.

Intents

Intents help you to send data from one Android Component to another. Code to use them can be cumbersome and long. Anko give you a more concise and pleasant way to use intents.

For example, in Kanime you show a list of animes in MainActivity, and when an anime is tapped, it will open AnimeDetailActivity with all the information about the anime.

For this reason, you need an Intent to open AnimeDetailActivity to pass it the information about the selected anime.

Lets see some code!

In the MainActivity.kt file find the function openDetailActivity() that opens the detail screen.

Here is what the code looks like without Anko. :[

private fun openDetailActivity(anime: Anime) {
  // 1 Create the intent and specify the target activity
  val intent = Intent(this, AnimeDetailActivity::class.java)

  // 2 Add anime details
  intent.putExtra("TITLE_KEY", anime.name)
  intent.putExtra("DESCRIPTION_KEY", anime.description)
  intent.putExtra("IMDB_LINK_KEY", anime.imdbLink)
  intent.putExtra("IMAGE_KEY", anime.imageDrawable)
  
  // 3. open the detail activity
  startActivity(intent)
    }

You create an Intent, then have a number of lines to add extras onto the Intent. There are a lot of steps and the end code is not pretty readable.

Replace the function with the equivalent code from Anko Commons:

private fun openDetailActivity(anime: Anime) {
  startActivity<AnimeDetailActivity>(
      "TITLE_KEY" to anime.name,
      "DESCRIPTION_KEY" to anime.description,
      "IMDB_LINK_KEY" to anime.imdbLink,
      "IMAGE_KEY" to anime.imageDrawable
    )
}

You need only one statement to achieve the same end and the code is completely readable!
You may need to hit Option+Return on Mac or Alt+Enter on PC to pull in the Anko extension function import.

To specify the target activity, you put the name of the class after the startActivity as <TargetActivity>. If you want to know more about how this works, read about Generics here.

To specify the additional data, you pass as arguments one or more Kotlin Pair objects to the function startActivity<TargetActivity>(). Each Pair is an extra that you are sending to the activity that you want to call.

A Pair is a class in Kotlin that helps you to store two values, and is similar to a Tuple in other languages.

If you got goosebumps, when you saw the to operator, don’t worry since it’s a shortcut infix function for creating Pair. The first parameter goes before the to and the second after to. For example:

This is the same as if you were to write:

Now you are a pair master :]

Quick Intro to Kotlin Pairs (Optional)

A Pair is a class in Kotlin that helps you to store two values, and is similar to a Tuple in other languages.

If you got goosebumps, when you saw the to operator, don’t worry since it’s a shortcut infix function for creating Pair. The first parameter goes before the to and the second after to. For example:

val myPair  = "TITLE_KEY" to "Berserk"
println("${myPair.first} ${myPair.second}")
// prints TITLE_KEY Berserk

This is the same as if you were to write:

val myPair2  = Pair("TITLE_KEY","Berserk")
println("${myPair2.first} ${myPair2.second}")
// Prints TITLE_KEY Berserk

Now you are a pair master :]

val myPair  = "TITLE_KEY" to "Berserk"
println("${myPair.first} ${myPair.second}")
// prints TITLE_KEY Berserk
val myPair2  = Pair("TITLE_KEY","Berserk")
println("${myPair2.first} ${myPair2.second}")
// Prints TITLE_KEY Berserk

Intent without passing data

When you tap the menu icon, Kanime opens AboutActivity.

In MainActivity, find the function openAboutActivity and replace it with the Anko version:

private fun openAboutActivity() {
  startActivity<AboutActivity>()
}

Here is the code prior to the switch to Anko:

private fun openAboutActivity() {
  val intent = Intent(this, AboutActivity::class.java)
  startActivity(intent)
}

Using Anko, with one line and a lot less code, you are able to open an activity without worrying about creating an Intent object.

Common Intents

Anko Commons offers a great set of “common” intents that are pretty easy to use. Take a look at the table below.

In AnimeDetailActivity, there are a lot of Intents like “share the anime with a friend” the anime and “open the IMDB profile of the anime in a web browser”.

share anime

Let’s see how you can improve AnimeDetailActivity using Anko Commons.

Share Anime

In AnimeDetailActivity, search for the function shareAnime() and update it with the Anko version:

private fun shareAnime() {
  share("$title \n $imdbLink", "Give a checkout to $title")
}

The non-Anko code looked like this:

private fun shareAnime() {
  val text = "$title \n $imdbLink"
  val subject = "Give a checkout to $title"
  
  //1. Creating the Intent
  val intent = Intent(android.content.Intent.ACTION_SEND)
  
  //2. Add extra data
  intent.type = "text/plain"
  intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject)
  intent.putExtra(android.content.Intent.EXTRA_TEXT, text)
  
  //3. open a list of possible apps that can handle this intent
  startActivity(Intent.createChooser(intent, null))
}

Nope, your eyes are not lying to you, this is for real!

With just one line, you are saving your self going off to search Google on the specific constants for the Intent for sharing with all the right parameters.

Open a Web browser

In AnimeDetailActivity, find the function openAnimeInTheBrowser() and update it to the Anko Version:

private fun openAnimeInTheBrowser(){
  browse(imdbLink)
}

Here is the code without Anko:

private fun openAnimeInTheBrowser(){
   val intent = Intent(Intent.ACTION_VIEW)
   intent.data = Uri.parse(imdbLink)
   startActivity(intent)
}

Again, a huge savings in code and improvement in readability!

Send an email

In AnimeDetailActivity, find the function sendAnimeByEmail() and modify it to the cool Anko version:

private fun sendAnimeByEmail(emailAddress: String, subject: String, body: String) {
  email(emailAddress, subject, body)
}

Here is the code without Anko:

private fun sendAnimeByEmail(emailAddress: String, subject: String, body: String) {
  //1. Creating the Intent
  val intent = Intent(Intent.ACTION_SENDTO)

  //2. Add extra data
  intent.data = Uri.parse("mailto:")
  intent.putExtra(Intent.EXTRA_EMAIL, arrayOf(emailAddress))
  intent.putExtra(Intent.EXTRA_SUBJECT, subject)
  intent.putExtra(Intent.EXTRA_TEXT, body)

  //3. Open the email app
  startActivity(intent)
}

You’ve again gone done to just one line of code with Anko!

Toasts, Snackbars and Dialogs

Dialogs are pretty important widgets when you want to communicate with your users, and Anko Commons make your life easier when working with them. It covers most of the more common widgets like Toast and SnackBars, and many flavors of Dialogs.

Toast

In AnimeDetailActivity, find the functions showShortToast and showLongToast and replace them with the Anko versions.

private fun showShortToast(message:String){
  toast(message)
}

private fun showLongToast(message: String) {
  longToast(message)
}

Here is the code without Anko:

private fun showShortToast(message: String) {
  Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

private fun showLongToast(message: String) {
  Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}

You’ve reduced a lot of the boilerplate by switching to Anko.

The best part of using toast() and longToast() is that you don’t have to call .show(), after creating the Toast, a million dollar mistake.

Also, toast() and longToast() offer helpful overloaded versions, accepting string resources and String objects, for example:

 
toast("message")
toast(R.string.message)
     
longToast("message")
longToast(R.string.message)