Summary of good points and precautions when converting Java Android application to Kotlin

Introduction

Perform steadily conversion during the 10 consecutive holidays I made my own Java Android application (about 300 files) into full Kotlin.

↓ Kotlin 100% diagram スクリーンショット 2019-05-03 2.11.20.png

Kolin First was announced at Google I / O 2019, which was held just after the 10th consecutive holidays. I'm going to have more opportunities to convert from Java to Kotlin, so I'll summarize what I stumbled upon and how to avoid it.

The environment is Android Studio 3.4.

Conversion method

You can be sure that everything is done manually, but Android Studio provides conversion commands. "Menu> Code> Convert Java File to Kotlin File" The shortcut is "Shift + Option + Command + k".

スクリーンショット 2019-05-14 7.58.17.png

Notes on Kotlin conversion command

comment

The comments sometimes hindered the conversion. The commented out part remains Java after Kotlin conversion. Also, Kotlin requires that you have the same number of / * to open comments and * / to close comments.

[Sample before conversion] スクリーンショット 2019-05-13 22.33.11.png

[Sample after conversion]

--The comment part remains Java --Insufficient number of comments to close Build error

スクリーンショット 2019-05-13 22.32.52.png

Nullable / NonNull is ambiguous

Kotlin is a NullSafe language specification, so if Nullable / NonNull is ambiguous on the Java side, It is treated as a platform type (a type that may be Nullable or NonNull). It is safer to treat it as Nullable unless NonNull is deterministic.

The code that actually caused a runtime error is below. Those with ! After the variable are platform type and can be treated as NonNull in the code. Null may come in at runtime and an error may occur. スクリーンショット 2019-05-09 3.47.20.png

Once it is treated as Nullable and early return etc., it can be treated as NonNull from the next line. スクリーンショット 2019-05-09 3.47.38.png

When defining a subclass of a class defined in Java in Kotlin

For Nullable / NonNull, when using Kotlin conversion command In particular, the following exceptions were likely to occur.

Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: 

This is an exception that occurs when the superclass is Java and the subclass is Kotlin and the non-null and null are mishandled. For example, an exception will occur in the following cases that inherit AppCompatActivity. It's a run-time error, so the code builds successfully.

class MainActivity : AppCompatActivity() {
:
    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        :

The correct code is to have Bundle? As the argument type, as shown below.

class MainActivity : AppCompatActivity() {
:
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        :

This is hard to find without reading the code on the superclass side. When I read the actual code, the Bundle is annotated with @Nullable. You can see that Bundle? Is correct instead of Bundle.

androidx-appcompat:[email protected]


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        final AppCompatDelegate delegate = getDelegate();
        delegate.installViewFactory();
        delegate.onCreate(savedInstanceState);

Good points to do before Kotlin conversion

Based on the above precautions, here are some things you should do before conversion.

Read documentation about Kotlin conversion

Both Kotlin official and Android official have interoperability documentation with Java.

Leverage NonNull annotations

It's better to distinguish NonNull as much as possible at the time of Java. According to the Kotlin documentation, the following annotations are supported.

https://kotlinlang.org/docs/reference/java-interop.html

JetBrains (@Nullable and @NotNull from the org.jetbrains.annotations package) Android (com.android.annotations and android.support.annotations) JSR-305 (javax.annotation, more details below) FindBugs (edu.umd.cs.findbugs.annotations) Eclipse (org.eclipse.jdt.annotation) Lombok (lombok.NonNull).

Compatible with Android X

If you are using the old support library, it is better to convert after migrating to Android X. Android X has less risk of conversion to Kotlin because NonNull and Nullable are clearly discriminated. Below is a comparison of Java code for RecyclerView.

Old support library RecyclerView https://android.googlesource.com/platform/frameworks/support/+/121ba96/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java#5143

        public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

RecyclerView in AndroidX library https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java#6888

        @NonNull
        public abstract VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType);

Guaranteed operation by unit test

If you add a unit test at the time of Java, it is easy to check the operation after Kotlin conversion. It is recommended to add a unit test as it is the minimum.

Take advantage of Lint

If you search for "interop" etc. in Editor> Inspection, the interoperable Lint that can be used for Kotlin conversion will be displayed. If checked, dangerous code will be warned before and after conversion.

https://developer.android.com/kotlin/interop#lint_checks https://developer.android.com/studio/write/lint?hl=ja

スクリーンショット 2019-05-13 23.04.38.png

Avoid variable names in Kotlin reserved words

Kotlin reserved words such as is, object, when, and get, set, etc. used in the internal Java code should be renamed in advance. You can use Kotlin by enclosing it in backticks, but you should avoid it.

Good points to do after Kotlin conversion

The Kotlin code generated by the Kotlin conversion command is hard to say that it utilizes Kotlin. At the very least, here's how to make it safe to some extent without warning.

Consider a Nullable type unwrap method

The code after the conversion command basically uses !! to unwrap it into NonNull. Consider whether it can be safely unwrapped with ? . etc.

Code example immediately after Kotlin conversion

    var webView: WebView? = null

    fun load() {
        if (webView != null) {
            webView!!.load()
        }
        :

Example of utilizing ?.

    var webView: WebView? = null

    fun load() {
        webView?.load()
        :

Consider whether the handling of var is appropriate

Consider whether Nullable properties can be used, such as lateinit and by lazy. If you want to initialize other than ʻinit such as ʻActivity # onCreate related to View, you can use lateinit to handle it as a property of NonNull.

    private var mRecyclerView: RecyclerView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
    :
        mRecyclerView = findViewById(R.id.recycler_view)
    private lateinit var mRecyclerView: RecyclerView

    override fun onCreate(savedInstanceState: Bundle?) {
    :
        mRecyclerView = findViewById(R.id.recycler_view)

Consider whether the constant val can be const val

In Java, static final constants are treated as val in the code after the Kotlin conversion command. Consider whether it can be const val (usually, if you follow Lint, you will add const)

    companion object {
        private val TAG = "MainActivity"
    companion object {
        private const val TAG = "MainActivity"

Take advantage of the Firebase Robo Test for finishing

After conversion, even if you think you wrote the test code properly, there may be bugs that are beyond your expectations. This can be prevented by having a third party or Robo test it. There are more types such as Nullable / NonNull / Platform, and more states such as lateinit before initialization. We recommend using the Firebase Robo Test to prevent "inadvertent mistakes".

スクリーンショット 2019-05-13 22.50.47.png ↑ Run-time error found in my Robo Test. A mistake that accessed lateinit before initialization.

Impressions of 100% Kotlin

Kotlin itself is refreshing, but errors tend to occur when bridging Kotlin ⇔ Java. It's a pretty thorny road, so it's better to have Java code that is safe in advance. Once converted, you can use useful functions such as Coroutine and extension functions to change your life.

Recommended Posts

Summary of good points and precautions when converting Java Android application to Kotlin
Summary of points I was worried about when migrating from java to kotlin
[Java Silver] Summary of points related to lambda expressions
I tried to summarize the basics of kotlin and java
[Android] Convert Android Java code to Kotlin
[Java] Shallow copy and deep copy when converting an array to List
[Caution !!] Precautions when converting Rails devise and view files to haml
[Android] Convert Map to JSON using GSON in Kotlin and Java
[Java Silver] Summary of access modifier points
I tried to summarize the stumbling points when developing an Android application
[java] Summary of how to handle char
Convert all Android apps (Java) to Kotlin
Summary of means when you want to communicate with HTTP on Android
[Java] Tips and error issues when converting from double to Big Decimal
[Java] [Maven3] Summary of how to use Maven3
Precautions when migrating from VB6.0 to JAVA
Summary of Java Math.random and import (Calendar)
Java to C and C to Java in Android Studio
Points I stumbled upon when creating an Android application [Updated from time to time]
Summary when trying to use Solr in Java and getting an error (Solr 6.x)
Kotlin functions and lambdas to send to Java developers
[java] Summary of how to handle character strings
Things to be aware of when writing Java
Java switch statement and break, Kotlin when expression ...
[Java] Personal summary of classes and methods (basic)
[Java] Summary of how to abbreviate lambda expressions
Summary of moss when updating from JMockit 1.4 to 1.30
What I did when I converted java to Kotlin
Precautions when converting from decimal number to binary number
Summary of copy and paste commands used when you want to delete the cache in iOS application development anyway
Technical causes and countermeasures for points addicted to Android apps & Kotlin (3. Processing related to Android images)
Installing Java is not easy! Summary of precautions to finish perfectly in one time
Summary of how to use the proxy set in IE when connecting with Java
[Java] Types of comments and how to write them
Summary of ToString behavior with Java and Groovy annotations
Please note the division (division) of java kotlin Int and Int
The comparison of enums is ==, and equals is good [Java]
Java language from the perspective of Kotlin and C #
Summary of knowledge required to pass Java SE8 Silver
Summary of Java communication API (1) How to use Socket
I want to transition screens with kotlin and java!
Summary of Java communication API (3) How to use SocketChannel
Summary of Java communication API (2) How to use HttpUrlConnection
Summary of how to implement default arguments in Java
[Java] [Kotlin] Generically call valueOf and values of Enum
[Java] Things to be aware of when outputting FizzBuzz
Technical causes and countermeasures for points addicted to Android apps & Kotlin (1. Android screen transition (fragment) processing)
A summary of what Java programmers find when reading Kotlin source for the first time
Android application development (supports both Java and Kotlin) How do you implement this? ~ Button edition ~
Android application development (supports both Java and Kotlin) How do you implement this? ~ Text Edition ~
[Android / Kotlin] UI summary
Technical causes and countermeasures for the points that I was addicted to with the Android app & Kotlin (2. Processing related to the camera function of Android *)
Summary of Java support 2018
Setting method to link Java of Eclipse and Github / September 2017
Java to fly data from Android to ROS of Jetson Nano
[Java] Precautions when converting variable-length argument parameters into an array
Generate and execute Jar file of Java file belonging to package
How to use trained model of tensorflow2.0 with Kotlin / Java
Refer to C ++ in the Android Studio module (Java / kotlin)
Command to check the number and status of Java threads
I want to make a list with kotlin and java!