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
You are currently viewing page 2 of 3 of this article. Click here to view the first page.

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.

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.

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!