How to crash the migration from Java to Kotlin in Android application
Ever since Google announced official support for Kotlin on Android, more and more developers want to use it in their new and existing projects. Since I'm also a big fan of Kotlin, I could not wait to be able to use Kotlin in my working project. In the end, Kotlin is fully compatible with Java, and all developers are simply delighted with this. So what can go wrong?
"Getting started with Kotlin" It's written that if you want to transfer an existing application to Kotlin, you just have to start writing unit tests, and then, after a little experience with this language, you must write new code on Kotlin, and convert the existing Java code.
In this article, I will tell you what would happen if I decided to immediately follow this strategy on the road, rather than try it on my pet project.
Meet my pet project
I had a project that I created over a year ago in Java, and I needed to change it a bit and add one new screen. I thought that this is a great opportunity to check whether the migration of the existing project to Kotlin is very simple, as everyone says. Based on the recommendations of the official documentation, I started by writing modular tests on Kotlin. I also wrote new classes on Kotlin and converted some existing ones. It seemed that everything was fine, but after a while I found one unpleasant problem.
Kotlin + Lombok =: (
In my application, I used the Lombok library to generate getters and setters. Lombok is an annotation handler for javac. Unfortunately, the kotlin compiler uses javac without processing annotations [источник] . This means that methods created with Lombok will not be available in Kotlin:
But you can say: "Well, it will not be very cool, but in principle you can manually create getters and setters for those fields that will be needed in the Kotlin code. In the end, you do not need to do this in the entire project at once. "
I thought the same. But I faced a real problem when I wanted to add a new screen to the application.
Kotlin + Lombok + Dagger 2 =: (((
In my application, Dagger 2 is used to implement dependencies. When creating a new screen, I usually create an MVP structure: Activity, Presenter, Component, Module, and Contract. All dependencies for the presenter are implemented using Dagger. Activity calls
DaggerSomeComponent.builder (). (). Build (). Inject (this) to introduce the presenter with the necessary dependencies for it.
Using Dagger 2 with Kotlin is no problem. Only before this, you need to apply
, which creates the necessary self-generated classes for Dagger.
And here everything starts to fall apart
Without a kapt plugin, I could not use the generated Dagger classes in Kotlin files. But after I added this plugin, all the methods created by Lombok have disappeared!
Before the application of
After the application of
And, unfortunately, there is no solution to this problem.
You can apply only a kapt plug-in, or only Lombok
. Luckily, since it was just my little pet project, I just deleted Lombok and myself wrote the getters and setters. But in this project there were only about 50 generated methods. In the project, which we support at work, we have them
about a thousand
. Removing Lombok from this application is simply impossible.
Also, it is obvious that the rejection of the kapt plug-in is not a way out of the situation. Without it, you can not use Kotlin in classes where Dagger is used. In my case, I would have to implement Activity, Component, and Module in Java, and only Contract and Presenter could be written on Kotlin. And mixing Java and Kotlin files is definitely not cool. Instead of a smooth transition from Java to Kotlin, you would simply create a big mess.
This would look like this awful polyglot MVP-structure without a kapt-plugin:
But I still want to go to Kotlin. What should I do?
One of the ways is
use different modules
. Kotlin will not see the methods that Lombok will generate in the source code, but will see them in bytecode.
Personally it seems to me that this is the most preferable way. If you display Kotlin in separate dependent modules for each feature, you reduce the risk of compatibility problems that I encountered, or the more complex ones listed in official guide .
And that is not all. In mixing Kotlin and Java files without a clear separation there are many other drawbacks. This makes all developers working with you on the project know both languages. Also this reduces the readability of the code and can lead to an increase in the build time of [источник] .
The methods generated by Lombok are not visible in Kotlin;
You can not use the self-generated classes for Dagger in Kotlin, which means that you still have to write new code in Java;
The way to solve this problem is to bring Kotlin into separate modules;
blending Kotlin and Java files in large projects without clear separation can lead to unexpected compatibility issues.
It may be interesting
Situs QQ Online
Situs QQ Online