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.
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
Android KTX Tutorial: Getting Started
20 mins
- Getting Started
- Collage Droid Structure
- Understanding Key Kotlin Features
- Extension Functions Fundamentals (Optional)
- Operator Overloading (Optional)
- Destructuring Declarations (Optional)
- Setting Up Android Core KTX
- Enhancing Collage Droid
- bundleOf
- drawToBitmap
- contentValuesOf
- Getting [] Operator on Menu
- More Gems of Android Core KTX
- Collection Extensions on ViewGroup
- View
- Uri
- SharedPreferences
- Anko vs. KTX
- Differences Between Anko and Android KTX
- Deciding When to Use Anko or Android KTX
- Where to Go From Here?
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! :]
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.
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.
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!