“Kotlin is a joke…”

Łukasz Wiśniewski
Stories from EyeEm

--

Just kidding, it’s great!

The new uploader for EyeEm Android was completely written from scratch in Kotlin. Our team of two started this project with zero knowledge of the language and in just 20 days had most of the features running. This post explains why we did it, how we did it and what we learned.

EyeEm for Android Upload Screen

Starting Out

We decided to go blindly with Kotlin for the next project — the decision was based on studies others have done before, and the fact Google officially backed the language during Google I/O 2017.

..and guess what? It was super easy and fun. Just write something in Java, then convert it to Kotlin. TADA!

Having said that, this article could end here. Yet another Kotlin success story.

App Architecture

EyeEm Android uses decorators to decompose presenter responsibilities. Every page is then dynamically resolved via router. Given the Kotlin-Java 100% interop, we just needed to write all new functionalities as decorators in Kotlin and keep existing decorators as they are — Java classes.

We’ve split the new upload functionality into four different screens. They are all specified in the router navigation file along with the appropriate decorators listed for each screen.

upload/:id/compose
upload/:id/location
upload/:id/tag/list
upload/:id/tag/create

Each screen relies on an :id . It is a reference to a record (a user draft of a photo he/she wants to upload) in the local Realm database.

This approach has a few benefits:

  • data persistence is at the core of the solution, user input is sacred
  • navigation doesn’t rely on a massive draft object passed via Intent class but rather just on a one simple string ID
  • each screen observes the changes in the realm database with the ID it has
  • as a developer you can jump to any screen from IDE without having to endure normal user journey (faster development cycle)

Meet Your New Companion

With Java we’ve hit a language barrier — some of our decorators would rely on having the following static method:

This method would take some information from the router context then based on that information prepare a configuration bundle for when the appropriate decorator is actually instantiated.

As a solution, we “hacked in” code generation into router plugin just to get away from this problem.

Kotlin lets you implement aforementioned configFor as a companion object interface.

This is a great way of enforcing static method contract without involving yourself into nasty hacks.

Delegate

Accessing decorator from a different decorator is quite a common task. It just got a lot simpler in Kotlin by using delegation pattern.

Then somewhere else in a decorator code you can just write this:

Your decorator now gets “injected” from the decorators’ context you work in.

Extensions

The obvious

Kotlin extensions are just great. End of line.

Chain it like a pro

For example, we can make Picasso API accept our EyeEm SDK Photo objects in just few lines of code:

then simply

Make SparseArray Great Again

If you‘ve ever came across SparseArray during your Android career you might have gotten annoyed by its poor API. Well… now with Kotlin you get to change that. Let’s start with overriding assignment operator!

The above enables you to do the following:

If that’s not enough, you can implement the missing iterator and much more, study the below snippet:

Your SparseArray is now fantastic.

Coroutines

If you haven’t yet heard about coroutines then you should watch this talk on coroutines by Roman Elizarov.

This is how EditText search input text debouncing could look like with no RxJava involved:

The above is an another extension method combined with a suspending function, full snippet here.

Data Class as a UI State

We found Kotlin data classes are a great tool for scoping UI state. Basically write what you want to have included in your UI state, e.g.:

Now you need to store your state somewhere, so:

Whenever you need to change a state, you reassign it using .copy(), e.g.:

React to changes using e.g. vetoable:

Here’s a post by Craig Russell explaining this even more in detail.

It’s a similar approach to redux. It makes your code deterministic and bugs easier to fix. This pattern also plays nicely with coroutines.

Memory Leaks

“A small leak will sink a great ship.” — Benjamin Franklin

Leaking Activity’s context in Android is one of the worst things to do and it was made super easy to accomplish with Java’s annonymous classes.

In Kotlin you have lambdas, they are much better by default — static. This shouldn’t let your guard down. If you pass around a strong context reference e.g. View object, you still risk leaking context.

The best way to find out what’s going on under the hood is Kotlin Bytecode Inspector. It’s integrated in IntelliJ and in just two clicks you can see how it’s all implemented in Java

  1. Tools > Kotlin > Show Kotlin Bytecode
  2. Decompile

The bad parts

Butterknife

Kotlin code converter didn’t “just work” with Butterknife. You end up with code like this:

or this:

Also unbinder.unbind() will nullify lateinit property :) At least in Kotlin 1.2 you should be able to check if lateinit property is initalized without throwing error.

Hopefully kotternife is there to rescue.

Realm

You need to keep your classes open and your fields nullable e.g.

This makes you either !! too much or use ?.let { }.

Flatbuffers

Currently there’s no official Kotlin binding. You can use Java one but it’s ugly. Hopefully this issue will get resolved at some point.

Books

I think we all love to read books from time to time. Here’s what helped me better understand Kotlin (apart from the stackoverflow and Kotlin forums).

Kotlin in Action

Kotlin’s point of reference. I started with the above book parallel to development of the upload feature. Chapter by chapter, it was a deep dive into Kotlin language features.

Kotlin For Android Developers

Having read the previous book, this one felt a bit repetitive in parts where Kotlin concepts where explained. However, if you want to start your Kotlin adventure with writing a sample app before anything else, then definitely take this book with you — it will be a pleasant journey.

Final thoughts

People don’t like change. Switching to a new programming language definitely is a thing that can bring some uncertainty. You might feel like you’re losing control — you were a Java expert and now you’re a noob in the brave new world of Kotlin. Fear not. The years of your expertise won’t just evaporate overnight. Software patterns stay the same, the frameworks too. You’re getting yourself a better tool to express your ideas, faster. If it doesn’t work out you can always go back to a previous commit— but I don’t think you will.

--

--