Android KTX Tutorial: Getting Started

In this tutorial, you’ll learn how to use Core KTX to make your code more concise and readable by refactoring an app that generates delightful collages. By Arturo Mejia.

Leave a rating/review
Download materials
Save for later
Share

Android KTX is one of the new kids in the Android Jetpack family. It’s a collection of Kotlin extension functions that will beautify and give a Kotlin-ish touch to existing Android APIs. KTX takes advantage of many of the awesome features in the Kotlin language to make all the old and rusty Java Android APIs feel like brand new.

Android KTX is an effort by the Google Android team to make the Android APIs more pleasant, idiomatic and easy to use for Kotlin developers, without adding any new features to the existing Android APIs. In this journey, you’re going to explore the APIs that Android KTX has to offer you

Why Is Android KTX Useful?

Android KTX simplifies your interaction with Android APIs by using features of the Kotlin language like extension functions, lambdas, and named and default parameters.

As an example, did you know that the class TextUtils has the methods isDigitsOnly and getTrimmedLength? Android KTX helps you discover many features on the Android APIs like these that you did not previously know existed because they were buried under tons of utility classes or static methods. Just by writing a dot after any object, you can now have a concise list of all the operations that you can apply to it, without having to memorize the methods in utility classes or make constant searches on Stack Overflow. This way, you can stand on the shoulders of giants and avoid code duplication.

Android KTX Packages

The KTX toolset is broken up into a number of different packages, so that you can import only the ones you need into your app project:

  • Core KTX: for use with framework APIs such as Toasts, Spans, and Menus
  • Fragment KTX: simplifies Fragment transactions
  • Palette KTX: for working with color palette APIs
  • SQLite KTX: simplifies SQLite database transactions
  • Collections KTX: for use with collection APIs
  • Navigation KTX: for use with Jetpack Navigation

In this tutorial, you’ll focus on the APIs that are wrapped by Core KTX.

Core KTX covers the Android framework APIs that are not tied to a specific component like fragments or SQLite. The following is a list of the packages included in core KTX:

Note: This tutorial assumes you have previous experience with Kotlin and Android. If you are unfamiliar with the language, have a look at this tutorial. If you’re just beginning with Android, check out some of our Getting Started and other Android tutorials.

Getting Started

Collage Droid is the app that you will use to use to see Core KTX in action — it’s an app that generates delightful photo collages. Along the way, you’re going to update it to take advantage of Core KTX goodies.

Download the Collage Droid project using the Download Materials button at the top or bottom of the tutorial. Open the starter project by using Android Studio 3.1.3 or later and selecting Open an existing Android Studio project:

Open an existing Android Studio project

Before going on with the tutorial, take a look at the existing starter code.

Collage Droid Structure

The Kotlin source code packages in the starter project appear as follows:

The Kotlin source files are:

  • MainActivity.kt
    This is the entry point of the app.
  • CollageFragment.kt
    This fragment is in charge of loading each photo template depending on which tab you selected.
  • TemplateType.kt
    An enum class that holds information related to every specific template; like the aspect ratio of the photos and which droid image should be presented by every template.

Now you have x-ray vision into how Collage Droid is structured!

Understanding Key Kotlin Features

Before you get started adding Core KTX code into the starter project, it’s worthwhile to look at how KTX works under the hood.

To enhance the Android APIs, Android KTX takes advantage of many awesome Kotlin features, like extension functions, operator overloading and destructuring declarations.

Note: If some of these topics are unfamiliar to you, take a look at the next few optional sections, which are denoted as “Optional” in the headers. If you are familiar with concepts, then feel free the skip these sections.

Extension Functions Fundamentals (Optional)

Extension functions allow you to add new functionality to an existing class, even without having access to the original class definition or source code.

For example, you already know that the class TextUtils has the method isDigitsOnly. To use it, you have to do something like this:

import android.text.TextUtils

fun test() {
  if (TextUtils.isDigitsOnly("123")) {
    //Do something
  }
}

But it makes more sense if the class String has this method itself, and you can then use it with any String instance, instead of having to call a static TextUtils method, like this:

fun test() {
  if ("123".isDigitsOnly()) { // Much nicer :]
    //Do something
  }
}

How can you achieve that? This is exactly what an extension function does. In another part of your code you define an extension function for the String class:

import android.text.TextUtils

//(1)  (2)   (3)
fun String.isDigitsOnly(): Boolean {
  return TextUtils.isDigitsOnly(this)
}

The following is going on in the extension function definition:

  1. The fun keyword.
  2. Name of the class to add the extension to followed by the dot(.) notation.
  3. The name of your new extension function.
Note: Inside the extension function, this is a reference to the caller object:
"1".isDigitsOnly() // this represents the String instance "1"

You can use an extension function by importing the file in which the extension function is defined.

Operator Overloading (Optional)

Did you know that in Kotlin you can change the behavior of common operators like +, * , [], and more?

Take a look at some niceties that Core KTX offers for you in the Menu class:

import android.view.Menu
import androidx.core.view.get
import androidx.core.view.minusAssign

fun myFunction(menu : Menu) {
  val firstMenuItem = menu[0] //Gets the first menu item.
  menu -= firstMenuItem // Removes the menu item from the menu object.
}

You’re able to use index notation on menu items and use the subtraction assignment operator right on the menu items themselves!

Behind the scenes, this operator overloading is occurring thanks to operator extension functions on the menu class:

import android.view.MenuItem

operator fun Menu.minusAssign(item: MenuItem) {
  return removeItem(item.itemId)
}

operator fun  Menu.get(index: Int): MenuItem {
  return getItem(index)
}

The only difference here is that you have to add the operator keyword before the fun keyword.

Destructuring Declarations (Optional)

Destructuring is a shortcut feature that allows you to break down an object into multiple variables and declare them in just one step.

For example, the Location class is primarily made up of two main variables latitude and longitude. Using destructuring declarations from Core KTX you can access the latitude and longitude as follows:

import androidx.core.location.component1
import androidx.core.location.component2

fun myFunction(location: Location) {
  val (lat, lon) = location
}

You assign (lat, lon) to the Location instance, and Kotlin extracts the parts of the location for you.

Behind the scenes, this is once again working thanks to extension functions:

package androidx.core.location

import android.location.Location

inline operator fun Location.component1() = this.latitude

inline operator fun Location.component2() = this.longitude

The Location class has to operator extension functions component1() and component2() that let you break the Location instance into parts.

The inline keyword is an optimization feature. If you want learn more take a look at here.

Enough with the theory! It’s time for you to start exploring Core KTX! :]

Android KTX

Setting Up Android Core KTX

You’ll improve Collage Droid by adding Core KTX!

To set it up in the project, you only need to include the Gradle dependency. Open the app module build.gradle file and add this line to your dependencies:

implementation "androidx.core:core-ktx:$androidx_version"

Core KTX is part of Android Jetpack, which is specified using an androidx dependency.

Note: As of the writing of this tutorial, the latest version of AndroidX is 1.0.0-beta01. You can find the last version of Android Core KTX here. Each new release comes with release notes for what has changed since the last version.

Also, be aware that to use the 1.0.0-beta01 version, you must target Android API Level 28 and migrate all your support library dependencies to AndroidX. If you just want to try Core KTX without migrating, you can use version 0.3 instead.

Click “Sync Now” to sync your Gradle files.

Awesome! Now you can use Core KTX in your project.

Enhancing Collage Droid

In Collage Droid, every time you tap a tab, the photo template changes; you do this by passing a Bundle object with the type of template that you want to present.

bundleOf

bundleOf is a Core KTX helper function that lets you create a Bundle object from anywhere.

In the CollageFragment.kt file, find the newInstance() function and replace it with this equivalent using bundleOf:

fun newInstance(templateType: TemplateType): CollageFragment {
  val fragment = CollageFragment()

  val bundle = bundleOf(ARG_TEMPLATE_TYPE to templateType.name)
  
  fragment.arguments = bundle
  return fragment
}

You may need to press Option+Return on Mac or Alt+Enter on PC to pull in the function import.

This how the code looked before:

fun newInstance(templateType: TemplateType): CollageFragment {
  val fragment = CollageFragment()
  
  val bundle = Bundle()
  bundle.putString(ARG_TEMPLATE_TYPE, templateType.name)
  
  fragment.arguments = bundle
  return fragment
}

Using bundleOf(), you avoid needing to first create a Bundle object and then making multiple put calls to add data into the Bundle. Instead, with Core KTX you pass one or many key/value arguments as Kotlin Pair objects using the to infix function into bundleOf() all at once.

So Core KTX has made your code more concise and readable with just this first simple change!

drawToBitmap

drawToBitmap() is an extension function on the View class. It converts a view to a Bitmap object; this will be pretty handy for creating the collages.

In the app, when you have completed all the image buckets, a check mark menu appears to let you generate a collage; you can improve the function that is in charge of that.

In CollageFragment, find the function viewToBitmap() and replace it with the KTX version:

private fun viewToBitmap(view: View): Bitmap {
  return view.drawToBitmap()
}

Here is the code prior to switching to KTX:

private fun viewToBitmap(view: View): Bitmap {
  // 1 Create a new bitmap with the view info
  val bitmap = Bitmap.createBitmap(view.width, view.height,
      Bitmap.Config.ARGB_8888)
  // 2 Draw the view pixes into the bitmap
  val canvas = Canvas(bitmap)
  view.draw(canvas)
  return bitmap
}

Using Core KTX, you killed the boilerplate Bitmap creation code and focused on the main goal.

contentValuesOf

Content providers are superb for sharing data between apps. After the app creates the collage, it stores it in the picture directory. To do that it uses a ContentValues object to share the metadata of the photo collage with other apps.

You can use the Core KTX contentValuesOf() function to create ContentValues objects in an easy and compact way.

alerts

In CollageFragment, find the function addImageToGallery and update it with the Core KTX version:

private fun addImageToGallery(cr: ContentResolver, imgType: String, filepath: File): Uri? {
  val currentTime = System.currentTimeMillis()
  val fileString = filepath.toString()

  val values = contentValuesOf(
      MIME_TYPE to "image/$imgType",
      DATE_ADDED to currentTime,
      DATE_TAKEN to currentTime,
      DATA to fileString
  )
  return cr.insert(EXTERNAL_CONTENT_URI, values)
}

Without Core KTX, the code looked as follows:

private fun addImageToGallery(cr: ContentResolver, imgType: String, filepath: File): Uri? {
  val values = ContentValues()
  val currentTime = System.currentTimeMillis()
  val fileString = filepath.toString()

  values.put(MIME_TYPE, "image/$imgType")
  values.put(DATE_ADDED, currentTime)
  values.put(DATE_TAKEN, currentTime)
  values.put(DATA, fileString)
  return cr.insert(EXTERNAL_CONTENT_URI, values)
}

The contentValuesOf() function has a similar syntax to bundleOf(). You pass the metadata values as pair objects rather than having to make a bunch of calls to put() functions.

Getting [] Operator on Menu

As you saw in one of the optional sections above, Kotlin lets you add new behavior to operators. In Core KTX, the Menu class has extended the get operator to give you an array-like syntax to access the menu elements.

In Collage Droid, once you’ve filled in all the image buckets on a tab, the check mark menu option is made visible.

In CollageFragment, search for the function hideMenuItemDone() and update it to a Core KTX version:

private fun hideMenuItemDone(menu: Menu) {
  menuDone = menu[0]
  menuDone.isVisible = false
}

Here is the code without Core KTX:

private fun hideMenuItemDone(menu: Menu) {
  menuDone = menu.getItem(0)
  menuDone.isVisible = false
}

As you can see, the Core KTX version takes full advantage of the Kotlin operator-overloading feature. It’s not a huge change to switch from using the getItem() method, but it makes your code a little more concise and readable.

Collage Droid is now completely using Core KTX!

More Gems of Android Core KTX

You’ve just scratched the surface in this tutorial on the power of Core KTX! This section discusses a few more features of the library.

Collection Extensions on ViewGroup

Core KTX added many goodies to the ViewGroup class to make it more like a collection. This makes a lot of sense because all ViewGroup children like FrameLayout, LinearLayout, RelativeLayout, and others are containers that have their own children views.

Some examples of the collection extensions for ViewGroup in Core KTX are seen in the following function:

fun example(context: Context) {
  val viewGroup = LinearLayout(context)

  val view1 = View(context)
  val view2 = View(context)

  //1 Adding children
  viewGroup += view1
  viewGroup += view2

  //2 
  viewGroup[0] // Will return view1
  viewGroup[1] // Will return view2

  //3 
  view1 in viewGroup // Will return true
  view2 !in viewGroup // Will return false

  //4 
  viewGroup.size // Will return 2

  //5 
  viewGroup.isEmpty() //Will return false
  viewGroup.isNotEmpty() //Will return true

  //6 
  viewGroup.forEach {
    // the variable it will has the actual view index

  }
  viewGroup.forEachIndexed { index, view ->
    // the variable index contains the actual index and view has the actual view object
  }

  for (view in viewGroup) {
    // view is the actual view object
  }

  //7 
  viewGroup -= view1
  viewGroup -= view2

}

The above examples include the following collection-like actions on a ViewGroup:

  1. Adding children
  2. Accessing children using the get operator []
  3. Checking if an element is in the ViewGroup
  4. Checking number of child elements using size
  5. isEmpty() and isNotEmpty()
  6. Looping over children
  7. Removing elements

View

The View class also has useful Core KTX features, as shown in the following example:

import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible

fun example(context: Context) {
  val view = View(context)

  //1
  if (view.isVisible) // Boolean instead of Int
    view.isVisible = false // Instead of View.GONE
  else
    view.isVisible = true // Instead of View.VISIBLE

  if (view.isInvisible) // Boolean instead of Int
    view.isInvisible = false // Instead of View.INVISIBLE
  else
    view.isInvisible = true // Instead of View.VISIBLE

  if (view.isGone) // Boolean instead of Int
    view.isGone = false // Instead of View.GONE
  else
    view.isGone = true // Instead of View.VISIBLE


  //2
  view.updatePadding(
      left = 0, top = 0,
      right = 0, bottom = 0
  )

  view.updatePadding(left = 0) //Just update the left and the others are default values

}

The possibilities for View using Core KTX include:

  1. Checking visibility
  2. Updating padding

Uri

The Uri class has some nice additions in Core KTX:

import androidx.core.net.toFile
import androidx.core.net.toUri

fun example() {

  val string = "https://test.example.com/foo?bar#baz"

  // 1
  val uri = string.toUri() // Uri object from String

  // 2
  val fileFromUri = uri.toFile() // File object from Uri object

  // 3
  val uriFromFile =  fileFromUri.toUri() // Uri object from File object

}

You have helpers to:

  1. Convert a String to a Uri
  2. Get a File object from a Uri

SharedPreferences

Getting an Editor for SharedPreferences can be a pain, and often you might forget to call apply() to persist the changes:

Core KTX has you covered:

import androidx.core.content.edit

fun example(context: Context) {

  val preferences = context.getSharedPreferences("prefs", 0)

  //1
  preferences.edit(commit = true) {
    putString("key1", "value")
    putInt("key2", 1)
  } //2

  //1
  preferences.edit {
    putString("key1", "value")
    putInt("key2", 1)
  } //2
  
}

For SharedPreferences, Core KTX offers:

  1. Calling edit() to get an Editor
  2. Not needing to call apply(), since Core KTX does it for you

Anko vs. KTX

Anko is a Kotlin library from JetBrains. It shares the goals with Android KTX of making your life as an Android developer easier and making your code more readable and pleasant to use. Android KTX and are Anko are similar but not quite the same.

Differences Between Anko and Android KTX

They have common goals but with different scopes in mind. The mission of KTX is to bring idiomatic APIs to Kotlin users. As is mentioned in the repository, KTX does not intend to add new functionality to the existing Android APIs.

Anko has a wider scope, and this gives it the flexibility to innovate and create new features (Anko Layouts and Anko Coroutines are examples).

Deciding When to Use Anko or Android KTX

Generally speaking, Anko and Android KTX cover different parts of the Android API, and there’s no reason you can’t use both in your project. Investigate each one individually and use either as much as you want in your projects!

Where to Go From Here?

You can download the final project with all the Android KTX changes using the Download Materials button at the top and bottom of the tutorial.

Now that you’ve gotten started with Core KTX, you should check out other parts of Android KTX, including its use for Fragments, Palette, SQLite, and Navigation.

I also suggest you to check out some other resources:

Remember that Core KTX is an open-source project and you can contribute to it in many ways: proposing new features, reporting bugs or submitting a pull request.

I hope you enjoyed this introduction to Android KTX. If you have any comments or questions, please join in on the forum discussion below.