Converting an android project to kotlin
This is a small write-up of my experiences from converting a native android-app from java to kotlin.
TLDR;
- Convert the project using android studio
- Handle nullability-compilation errors
- Android annotations
- build script
- apply lateinit on @ViewById
- Convert your data-objects into small classes, go for immutable classes
- Kotlin is cool, and immutability rocks. Bugs in android-studio shows that it is still early days for kotlin-development on android.
Convert your project!
The first step is easy, android-studio will do most of the work for you. To convert the existing javacode into kotlin, simply select the src/main/java folder in the project and choose Code->"Convert Java File to Kotlin File”. Android studio will then try as best as it can to convert all your java-code to kotlin-code.
Android studio will convert all your .java files into .kt files in-place, leaving them in src/main/java.
Your project will probably not compile now, because of differences in how java and kotlin handles nullability.
nullability(.!!?) issues
One of the big advantages kotlin has over java is the handling of nullability. By default, an object is non-nullable and has to explicitly specified to be nullable.
In my case, android-studio generated code that would not compile. My data-objects were converted to have nullable-fields, but several kotlin-functions specified non-nullable arguments. To fix this, simply allow nullable-arguments or, even better, make your data-objects immutable with non-nullable fields!
error after automatic conversion in android-studio :
The generated nullable field in the class “Shipment:”
class Shipment {
var shipmentNumber: String? = null
...
Simply change this class to an immutable version, by specifying the arguments in a constructor:
class Shipment(val shipmentNumber: kotlin.String, /* other fields goes here */)
Android-annotations (if applicable)
When android-studio converted your project, it most likely broke the usage of your android-annotations usage.
To use android-annotations, add the kotlin-kapt plugin to your build-script and add the android-annotations-dependency to the kapt-configuration:
...
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
...
dependencies{
...
kapt "org.androidannotations:androidannotations:4.3.1"
}
The fields marked with @ViewById will make the annotation-processor complain with the following error:
org.androidannotations.annotations.ViewById cannot be used on a private element
To resolve this, change the generated code:
@ViewById(R.id.adView)
var adView: AdView? = null
by adding lateinit and removing the nullability:
@ViewById(R.id.adView)
lateinit var adView: AdView
The lateinit keyword in kotlin means that the field can be treated as non-nullable, but will be initialized after the constructor has been called (for the purpose of dependency-injection and lazy-initialization).
After removing the nullability-option on the view-fields, the “!!” notation on references to these fields can be removed.
Other thoughts
Even if it is several months since the announcement for kotlin-support on android, the kotlin-plugin for android studio seems somewhat immature. During my little experience with kotlin in android-studio the plugin has crashed several times and I had to restart android studio to continue working.
I also tried to change the folder-name for my kotlin source-code from src/main/java to src/main/kotlin, but this caused android studio to stop giving lint-hints and auto-completion even if some of the code was highlighted properly.
These two issues makes me think that kotlin might still be in its early days on android and that more improvements can be done to improve developer satisfaction.
However, the advantages that kotlin brings with easier-to-read code and immutability are welcome features that will help avoiding bugs and ease both maintenance and writing of apps for android. A simple(and a bit naive) measure of maintanability is lines of code(LOC), in my case I reduced the LOC by about 33%:
LOC Before(java) | LOC After(kotlin) |
---|---|
6540 | 4389 |