December 14, 2019 By Alex

16 Kotlin Tips for Android Development


Savvy Apps started using Kotlin for its new Android projects late in 2016, right around when Kotlin 1.0.4 was released. Initially, we saw an opportunity to try out Kotlin on a smaller scale project. Once we tried it out and saw the ease of use, being able to easily separate functionality from business logic using extensions, and generally, the hours of development time it saved for us, we decided it would be the language of choice moving forward. Since then, we've used Kotlin to create multiple Android apps and have also developed a number of internal Kotlin libraries.

To build off our experience with Kotlin, we decided to compile our most useful and favorite tips across Savvy's collective Android development team. Before reading these tips, you should check out the Kotlin documentation and explore the language for yourself at Since these tips focus specifically on using Kotlin within the context of Android development, you should have experience with the Android SDK as well. You should also be familiar with the Kotlin plugin and using Kotlin with Android Studio, which is provided by JetBrains, the creators of Kotlin.

Note: These tips are ordered based on your familiarity with Kotlin so you can easily skip to tips that suit your skill level.

Initial Kotlin Tips for Android


There are several benefits to lazy loading. Lazy loading can result in faster startup time, since loading is deferred to when the variable is accessed. This is particularly useful in using Kotlin for an Android app as opposed to a server app. For Android apps, we want to reduce app startup time so that the user sees the app content faster, rather than sitting at an initial loading screen.

Lazy loading like this is also more memory efficient, as we only load the resource into memory if it is called upon. Memory usage is important on mobile platforms like Android, since phones have limited, shared resources. For example, if you are creating a shopping app, and there is a possibility that users will only browse your selection, you could have the actual purchasing API be lazy loaded:

val purchasingApi: PurchasingApi by lazy {
val retrofit: Retrofit = Retrofit.Builder()

By using lazy loading like this, if the user never attempts to check out in the app, you will never load the PurchasingApi, and therefore will not use up the resources it would take.

Lazy loading is also a good way to encapsulate initialization logic:

// bounds is created as soon as the first call to bounds is made
val bounds: RectF by lazy {
RectF(0f, 0f, width.toFloat(), height.toFloat())

As soon as the first reference to bounds is made, the RectF is created, using the view's current width and height, saving us from having to explicitly create this RectF, then set it later on.


Kotlin's custom getters and setters use the structure of a model, but specify custom behavior to get and set the fields. When using custom models for certain frameworks, such as the Parse SDK, you are fetching values that are not actually local variables in the class, but are stored and retrieved in some custom way, such as from JSON. By using custom defined getters and setters, we can simplify the access:

class Book : ParseObject() {

// getString() and put() are methods that come from ParseObject
var name: String
get() = getString("name")
set(value) = put("name", value)

var author: String
get() = getString("author")
set(value) = put("author", value)

Fetching these values would look similar to using property access syntax with other models:

val book = api.getBook()
textAuthor.text =

Now if your model needed to change from Parse to some other data source, your code would potentially only need to be changed in one place.


Lambdas reduce the overall lines of code in a source file and allow for functional programming. While lambdas are currently possible with Android, Kotlin takes them a step further by ensuring you don't have to deal with Retrolambda or changing the way your build is configured.

For example, an on-click listener would look like:

button.setOnClickListener { view ->

It even works with return values:

toolbar.setOnLongClickListener {

The Android SDK contains plenty of cases where you are setting a listener or implementing a single method. Lambdas work great in those circumstances.


Data classes simplify classes, adding equals()hashCode()copy(), and toString() methods automatically. They clarify the intention of the model and what should go in it, separating pure data from business logic.

Take a look at this data class as an example:

<code class=" language-javascript">data <span class="token keyword">class</span> <span class="token class-name">User</span><span class="token punctuation">(</span>val name<span class="token punctuation">:</span> String<span class="token punctuation">,</span> val age<span class="token punctuation">:</span> Int<span class="token punctuation">)</span></code>

That's it. Nothing else is needed to make this class work. If you are using data classes with something like Gson or another JSON parsing library, you can create the default constructor with default values like so:

// Example with Gson's @SerializedName annotation
data class User(
@SerializedName("name") val name: String = "",
@SerializedName("age") val age: Int = 0

Collections are dealt with quite often when working with an API. More often then not, you want to filter or modify the contents of that collection. By using Kotlin's collection filtering, adding clarity and making your code more succinct. It's easier to tell what your resulting list should contain with collection filtering like the following:

val users = api.getUsers()
// we only want to show the active users in one list
val activeUsersNames = items.filter { // the "it" variable is the parameter for single parameter lamdba functions

Filtering a collection using the built-in Kotlin methods is very comparable to other functional programming languages too, such as Java 8 streams or Swift collection types. Being able to filter collections in a unified way helps when talking with team members about what operations need to be done to get a list down to the right elements to display.


Object expressions allow for strict singleton definition so there's no mistaking it for a class that can be instantiated. They also ensure that you do not have to store singletons somewhere like in the Application class or as a static class variable.

For example, if I have a utility class with static thread-related methods I want to access throughout the app:

package com.savvyapps.example.util

import android.os.Handler
import android.os.Looper

// notice that this is object instead of class
object ThreadUtil {

fun onMainThread(runnable: Runnable) {
val mainHandler = Handler(Looper.getMainLooper())

ThreadUtil is called later in the typical way you would call a static class method:

<code class=" language-javascript">ThreadUtil<span class="token punctuation">.</span><span class="token function">onMainThread</span><span class="token punctuation">(</span>runnable<span class="token punctuation">)</span></code>

This means there's no more declaring a constructor as private, or having to figure out where the static instance is stored. Objects are essentially first class citizens of the language. In a similar way, we create objects instead of anonymous inner classes:

viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}

override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}

override fun onPageSelected(position: Int) {

Both of these do essentially the same thing -- create a single instance of a class as a declared object.


At a glance, Kotlin appears to be missing static variables and methods. In a sense, it does not have these concepts, but instead has the idea of companion objects. These companion objects are singleton objects within a class which contain the methods and variables you might want to access in a static fashion. A companion object allows defined constants and methods, similar to static in Java. With it, you can follow the newInstance pattern of fragments.

Here's a look at a companion object in its simplest form:

class User {

companion object {
const val DEFAULT_USER_AGE = 30

// later, accessed like you would a static variable:
user.age = User.DEFAULT_USER_AGE

In Android, we commonly use static methods and variables to create static factories for fragments or activity intents. For example:

class ViewUserActivity : AppCompatActivity() {

companion object {

const val KEY_USER = "user"

fun intent(context: Context, user: User): Intent {
val intent = Intent(context,
intent.putExtra(KEY_USER, user)
return intent

override fun onCreate(savedInstanceState: Bundle?) {

val user = intent.getParcelableExtra<User>(KEY_USER)

The call to create this Intent looks and feels familiar to what you would see in Java:

val intent = ViewUserActivity.intent(context, user)

This pattern is great, since it reduces the likelihood that an Intent or Fragment would be missing the needed data to display a user or whatever content it is meant to display. Companion objects are a way to keep some form of static access within Kotlin, and should be used accordingly.


Kotlin allows you to define constants that span across an entire app in one place (if applicable). Typically, constants should have their scope reduced as much as possible, but when scope needs to be global this is a great way to do so without having to go through a constants class.

package com.savvyapps.example


// Note that this is not a class, or an object
const val PRESENTATION_MODE_PRESENTING = "presenting"
const val PRESENTATION_MODE_EDITING = "editing"

These can be used as constants anywhere in your project:

import com.savvyapps.example.PRESENTATION_MODE_EDITING

val currentPresentationMode = PRESENTATION_MODE_EDITING

Keep in mind that constants should be kept to as small a scope as possible to reduce complexity. If you have a value that only relates to the user class, put the value there in a companion object instead.


Optional parameters make method calls more flexible without having to pass null or a default value. This is especially useful when defining animations.

For example, if you want to have a method defined for fading out views throughout your app, but only in special circumstances do you need to specify the duration, you can define your method like so:

fun View.fadeOut(duration: Long = 500): ViewPropertyAnimator {
return animate()
icon.fadeOut() // fade out with default time (500)
icon.fadeOut(1000) // fade out with custom time

Intermediate Kotlin Tips for Android


Extensions are useful because they allow you to add to the functionality of a class without having to inherit from it. For example, have you ever wished Activity had some method, such as hideKeyboard()? With extensions, you can accomplish this easily:

fun Activity.hideKeyboard(): Boolean {
val view = currentFocus
view?.let {
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE)
as InputMethodManager
return inputMethodManager.hideSoftInputFromWindow(view.windowToken,
return false

With extensions you can easily eliminate the need to have utility classes or methods, and can really improve the readability of your code. We like to take this a step further, and use extensions to improve the organization of our code as well. For example, imagine that you have a basic model, such as an article. This article is probably treated as a data class, which has been fetched from a source such as an API:

<code class=" language-javascript"><span class="token keyword">class</span> <span class="token class-name">Article</span><span class="token punctuation">(</span>val title<span class="token punctuation">:</span> String<span class="token punctuation">,</span> val numberOfViews<span class="token punctuation">:</span> Int<span class="token punctuation">,</span> val topic<span class="token punctuation">:</span> String<span class="token punctuation">)</span></code>

Say that you want to determine the relevance of an Article to a user based on some formula. Should you put this directly in the Article class? Some would say that model should only hold the data from the API, nothing more. In this case, extensions can once again work great for you:

// In another Kotlin file, possibly named ArticleLogic.kt or something simil

About Author

Subscribe our newsletter to get
latest news & updates

Lorem ipsum dolor sit amet consectetur adipiscing elit