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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
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 :]
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”.
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)