ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Kotlin + Android: Anko Commons

Sindre Moen
ProAndroidDev
Published in
8 min readNov 9, 2017

Hi, and welcome to the first part of my series on Kotlin and Android essentials. In this series, I’m going to have a look at some libraries and tools that I find essential when writing Android apps using the Kotlin programming language. We’ll start off pretty basic in this first post, where I’ll cover a very popular library by JetBrains themselves, namely Anko, a library made specifically for Android development in Kotlin.

Anko is probably mostly known for its very neat view DSL, which makes it much more pleasant to write view code without ever having to touch XML. While this has quite a few benefits in itself (performance and type safety comes to mind), I’m not going to talk about the DSL in this post. Instead, I’ll focus on the lesser known parts of Anko, which in my opinion is reason enough to include the library (or libraries) into your app. All of the stuff I’ll cover here is part of what they group together as the Anko Commons library.

Just so we’re clear, you add the library just like any other library in Android these days. Add the dependencies into your module’s build.gradle file and you’re good to go:

implementation "org.jetbrains.anko:anko-commons:$ankoVersion"

Remember to add your desired version of Anko into your project’s ext properties. By the time of this writing, the latest version is 0.10.2.

With that in place, let’s get down to business! So, what can Anko actually do for us to makes Android development in Kotlin a more pleasant experience? Mostly it boils down to extending existing the Android framework with some Kotlin niceties, to reduce the need for the boilerplate code and ceremony that often follows working with the Android framework. This, in turn, will also make your code less error prone as well, since you’re writing less code to perform the same operations.

Alright, enough talk, let’s see some code. Let’s begin with the all of the ceremony surrounding the simple task of navigating from an activity to another in Android. Consider two activities, one that shows a list of items, and another that shows the details for a specific item. In Java and using the Android framework directly, that’d look something like this:

Intent intent = new Intent(this, DetailsActivity.class);
intent.putExtra("id", item.id);
startActivity(this, intent);

Three lines just for navigating from one screen to another‽ Granted, one line is for adding the specific information as to which item to show the details for, but still, it feels like too much work, especially when you can do the same with Kotlin and Anko like this:

startActivity<DetailsActivity>("id" to item.id)

That’s it. It conveys the same information, just in a much more concise and expressive way. To me, that’s a clear win!

The only gotcha you should keep in mind when passing in those extras is that it’s not entirely type safe during compilation. While Android’s putExtra method ensures (through overloading) that you’re only able to pass in supported types as the second argument, Anko essentially accepts an Array<Pair<String, Any>>, and if there is no putExtra that matches the passed in value, an AnkoException will be thrown at runtime. Unfortunately, since the accepted types don’t have a common ancestor, this is a limitation we’ll just have to live with.

Oh, and if you added the support-v4-commons library as well, then startActivity has also been added as extension functions to your support fragments, so you can write the exact same code there.

By the way, while we’re on the topic of intents, Anko also provides a couple of other helpers for doing “regular” tasks such as sharing text, browsing URLs or sending e-mails, among other things. Check out the intent helper documentation for more information about what Anko provides in this area.

Just a simple task like showing a dialog box, toast or snackbar, also requires quite a bit of code on Android. The toasts are probably the simplest to make. (Thanks to Kanye West, we’ve even got an example text to use!)

Toast.makeText(
this, /* a context in which to show the toast */
"A toast for the douchebags!", /* the text to show */
Toast.LENGTH_SHORT /* the duration of the toast */
).show();

It’s no surprise that this is a lot simpler with Anko in place:

toast("A toast for the douchebags!")

That’s it! toast will use the Toast.LENGTH_SHORT duration. If you want to show the toast for a longer duration (i.e. Toast.LENGTH_LONG, which is the only other predefined length provided by the Android framework), just use longToast instead:

longToast("A longer toast for the douchebags!")

Snackbars require a little more work if they’ve got actions attached to them. This usually looks something like this:

Snackbar snackbar = Snackbar.make(
view,
"Let's have a toast for the douchebags!",
Snackbar.LENGTH_SHORT
);
snackbar.setAction("Cheers", new View.OnClickListener {
@Override
public void onClick(View view) {
haveToastForDouchebags();
}
});
snackbar.show();

Okay, that’s a lot of code. Arguably, most of this comes from adding the click listener, and in Kotlin we’d be able to use SAM conversion to mitigate some of this, but we can make it even nicer using Anko’s helpers:

snackbar(view, "Let's have a toast for the douchebags!", "Cheers") {
haveToastForDouchebags()
}

This feels way more in line with the expressiveness that we know from Kotlin already, and eliminates potential problems, like forgetting to call show, which many new Android developers tend to do. (That’s probably why there are specific lint checks in Android Studio to help you remember this!)

Of course, these functions also accept string resources, so you’ll still be able to provide those precious translations for your users!

toast(R.string.runaway_toast)snackbar(view, R.string.runaway_toast)

Anko also provides similar functions for showing alerts, selectors and progress dialogs. Make sure to check out the dialog docs, which are as concise as the functions themselves. Once you start using these, you’ll never understand how the default framework require all of that boilerplate code to perform the same tasks.

Anko Commons doesn’t just provide UI related helpers, it’s also aiming to make logging more straightforward through their AnkoLogger interface. Logging in Android happens through the framework-provided Log class. Logging requires a log tag string and a message, the former being used to group multiple log entries. It’s common practice to use the class name as the log tag, which is mostly kept as a field in the class for easy reference.

class LoggingClass {
private static final String LOG_TAG
= LoggingClass.class.getSimpleName();

public void logSomething() {
Log.i(LOG_TAG, "Message logged at INFO level");
}
}

But it turns out that log levels also have another use case that is less known. It may be that the log tag in question is not set up to be “allowed” to log to a specific log level (e.g., warnings and errors). For some reason, the implementations of Log.i, Log.w, Log.e, etc. don’t actually care about this and will log to whatever level you specify anyways. Since such a mechanism does exist in the system, however, it only makes sense to put it to use. That means that our above logging function should look something like this instead:

public void logSomething() {
if (Log.isLoggable(LOG_TAG, Log.INFO)) {
Log.i(LOG_TAG, "Message logged at INFO level if allowed");
}
}

Okay, still not completely awful, but it sure feels like this should be handled by the logging function itself! And since having the log tag be the name of the logging class is common practice, wouldn’t it be nice if we could just get that in there for free? Once again, Anko to the rescue! Here’s the whole above class, rewritten in Kotlin and logging with Anko:

class LoggingClass : AnkoLogger {
fun logSomething() {
info("Message logged at INFO level if allowed")
}
}

This does exactly the same as the Java version above (including the isLoggable check), but it’s much more concise!

The info function, along with its relatives verbose, debug, warn, error, and wtf, match the static Log.i, Log.v, Log.d, Log.w, Log.e and Log.wtf, respectively. They all come from the AnkoLogger interface and will by default use the class name of the class that implements the interface as the log tag, as common practice dictates.

One important thing to keep in mind , though, is that the Kotlin core library also comes with a system-wide error function. This function doesn’t log errors like the AnkoLogger one does, but instead throws an IllegalStateException with the given message.

Make sure that you have imported the error function from Anko when you use it in your code, lest you’ll get exceptions thrown when all you want to do is log some errors. And that would suck.

All of the logging functions have lazy versions as well:

info { "Messages logged at INFO level if allowed" }

The benefit of using this version of the function is that the lambda will only execute if the log tag can log at the specified log level. Thus, if whatever you’re logging requires some kind of computation beforehand, you can put this into the lambda and know that the computation won’t happen unless it’s going to get logged afterwards. Another benefit (probably unintentional from the library developers’ perspective) to using this is to ensure that Anko’s error function is used instead of Kotlin’s core version, since Anko’s is the only one of those that can take a lambda parameter.

Okay, so we’re nearing the end here. There’s just one small extra feature of Anko that I’d like to mention. Even if it is very small, it’s such a great little thing that I find myself using all the time, so it’s definitely worth a mention. I’m talking about a couple of functions that allow you to easily work with dips (density-independent pixels) in your Kotlin code. You’re going to need a context, since this is a requirement to be able to figure out the screen density of the device you’re currently running on, but given that, the process is straightforward:

val twelveDips = context.dip(12)

Doing the same in Java would require something like this:

Resources resources = context.getResources();
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
float density = displayMetrics.density;

int twelveDips = (int) (12 * density);

This will give you a pixel value equivalent of 12dip on your current device, no matter if it’s hdpi, xhdpi, xxhdpi or whatever. This is a life saver in so many cases when manipulating view in your code. In addition, the sp function will do the same, just for scale-independent pixels, in case you’re working with fonts as well.

Of course, you can also reverse the process if you need that:

context.px2dip(16)context.px2sp(16)

Okay, that about wraps it up for this one, guys! It’s been fairly basic for now, but in future posts in this series I’ll have a go at some more complex things, like dependency injection and testing. Thanks for reading, and make sure to stay tuned for more Kotlin and Android goodness!

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

No responses yet

Write a response