Category Archives: Kotlin

I Know Nothing in Kotlin

When the Greek philosopher Socrates professed that “I know only one thing– that I know nothing,” he wasn’t exactly professing ignorance. It was an ancient formulation of the Dunning-Kruger effect. He had discovered that the more he learned, the wider the expanse of human knowledge seemed and the less that it seemed he knew.

A fool, on the other hand, might believe that they’re “not smart, but genius….and a very stable genius at that,” and that they know “only the best words.”

In this sense, it’s a good thing to know nothing. It’s also true in Kotlin.

During a recent code pairing session, I discovered that in Kotlin, there are numerous developers who have written code in the language for many years. And yet, they still don’t know Nothing.

Our pairing session became a big fuss about Nothing. We were working on some Repository code in our shared Kotlin Multiplatform Mobile (KMM) module of our Meetup for Organizers app. In this code, there was a repeated block at the end of every repository call to handle network, DNS, and timeout errors. We decided it would make sense to refactor this block into a function as we used it so often.

The repeated block in question handled a catch block. It had to re-throw any CancellationExceptions to allow cooperative cancellation of coroutines. Then we had to wrap any other exception and re-throw it as a custom exception type so that we can easily tell iOS a complete list of all types we intend to throw in a @Throws declaration. This allows exception handling and to avoid crashing when our functions are called by Swift code. In essence, this code block always threw an Exception.

The pairing session became quite funny like the Laurel and Hardy “Who’s on First” comedy routine, but you could tell there was Nothing more frustrating, too. It went something like this:

“Why am I getting this red text at the call site?”

“The return type is incorrect because you always throw an exception. You need to return Nothing.”

“I already am returning nothing.”

“No, you’re returning Unit. All Kotlin functions return Unit if you don’t declare a type. You need to return Nothing.”

“I don’t understand. I’m returning nothing from the function.”

“Just trust me. Add it to the return type of the function: Upper case N- lowercase o…”

“I’m so confused.”

It turns out that my colleagues, who had been coding in Kotlin for many years, had never been exposed to Nothing.

Nothing is weird. Nothing is esoteric. But Nothing is quite so useful in these rare cases.

I know Nothing.

“Nothing has no instances. You can use Nothing to represent ‘a value that never exists’: for example, if a function has the return type of Nothing, it means that it never returns (always throws an exception).”

— Kotlin Documentation

The official definition only seems to raise further questions for newcomers to the language.

Why can’t I just return Unit?

Returning Unit would be lying to the compiler and the compiler will miss opportunities to do the right thing. For example, the code in our repository wouldn’t compile because we promised to return a type that wasn’t Unit from each function. Returning Nothing allows our parent function to compile and return the correct type.

What benefits do I get from Nothing?

You do, indeed, get something for Nothing. For one, not using Nothing misses out on correctness benefits like highlighting code as dead and unreachable if we run any code after our function that returns Nothing. Your IDE knows quickly that it stops at Nothing to show the right warnings. If we wrote the same code in Java, there would be no warnings.

Generics are also an area that is good for Nothing. If you want to create an object inside a templated sealed class that doesn’t have any type, its type is Nothing. Any other solution won’t compile.

// credit to Allan Caine @ Kotlin Academy
sealed class LinkedList<out T>  {

    data class Node<T>(val payload: T, var next: LinkedList<T> = EmptyList) : LinkedList<T>()

    object EmptyList : LinkedList<Nothing>() 
}

Nothing doesn’t only apply to functions where you always throw. Nothing is valuable for early returns, such as replicating the Swift guard() function in Kotlin:

// credit to Zac Sweers
inline infix fun <T> T?.guard(block: () -> Nothing): T {
  return this ?: block()
}

fun sweetNothings(input: String?) {
  val value = input guard {
    show("input is null!")
    return
  }
}

Why doesn’t Kotlin just determine automatically that my function returns Nothing and handle this for me?

As to my third and final question, automatically determining that a function returns Nothing would cause a number of problems. Both the compiler and IDE checks would take longer to run as they need to test every branch. Automated type inference would produce some surprising types that could lead to later bugs.

Finally, we should tell the creators of Kotlin, “Thanks for Nothing!”

If you enjoyed my blog post, you ain’t seen Nothing yet. Subscribe to my RSS and keep reading!

A dispatcher of many threads

Kotlin Coroutines have been almost unanimously received with applause by the Android software development community. However, there are some significant issues I have noticed in practice that are still unknown to most teams.

This week, one major issue was finally resolved.

Dispatchers.Main

Dispatchers.Main is the Kotlin Coroutines thread dispatcher for accessing Android’s main thread. Until recent improvements, the very first time this call is used, most apps experience a delay of up to a quarter second. Blocking the main thread pauses drawing the user interface and is enough to cause a noticeable lag to users.

It takes 16ms to draw one frame on Android. Blocking the main UI thread for 250ms skips fifteen frames at 60fps or thirty frames at 120fps. This is in addition to any other slow, blocking operations that might occur during your application’s initial startup.

This blocking operation serves no purpose. The Main Dispatcher was written using a ServiceLoader call. This choice resulted in a wasteful checksum operation being performed on the entire JAR file inside the APK.

I was able to workaround this problem several months ago on Firefox Preview by using a pre-release version of Google’s R8 code stripper along with custom rules. This wasn’t ideal. We were potentially subjecting our app to early stage bugs and were unlikely to get the same level of support for an unreleased version. We made this sacrifice because a quarter second startup time reduction was worth the cost.

At long last, there’s now a solution in a stable version of the Kotlin coroutines library itself. To take advantage of this fix, you must perform the following steps.

  1. Upgrade your version of Kotlin coroutines to 1.3.3 or higher in your build.gradle dependencies.
  2. Insert the required Proguard rules into your proguard-rules.pro file or whatever you’ve named it. See below.
  3. Ensure you’re using proguard-android-optimize.txt instead of the default, non-optimizing version.
  4. Ensure R8 is enabled. The R8 code stripper was introduced in Android Studio 3.3.0 and became default in Android Studio 3.4.0 or greater. It replaces Proguard’s code stripper, but should accept the same rules files. It can be configured in the gradle.properties file at the root of your application code.
# Add or replace these lines in your build.gradle file
# dependencies section
implementation org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3
implementation org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3
# Add these lines to proguard-rules.pro

# Allow R8 to optimize away the FastServiceLoader.
# Together with ServiceLoader optimization in R8
# this results in direct instantiation when loading Dispatchers.Main
-assumenosideeffects class kotlinx.coroutines.internal.MainDispatcherLoader {
    boolean FAST_SERVICE_LOADER_ENABLED return false;
}

-assumenosideeffects class kotlinx.coroutines.internal.FastServiceLoader {
    boolean ANDROID_DETECTED return true;
}
# Add these lines to your application build.gradle file
# or simply change the getDefaultProguardFile line

android {
   buildTypes {
      release {
        shrinkResources true
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
      }
   }
}
# Put this line somewhere in gradle.properties
android.enableR8=true

If you perform the above steps, gradle sync, and then perform a release build with optimization enabled, you should see a significant improvement in your cold start time versus previous release builds.

There are many options to quickly see this improvement with a flame chart. You could use Google’s Traceview or a dedicated, third-party tool like Nimbledroid.

Google’s new Jetpack Benchmark tool seems useful for UI code, but it is not recommended by its creators for measuring cold application startup time.

Update: I was planning a part two of this blog, but decided the second issue wasn’t as interesting, nor as clearcut as I expected for a blog post.