Androidアプリ(Java)をKotlinに全変換

##概要
会社のアプリをJava -> Kotlinに変換したいと思い、まず試しに自分のAndroidアプリ(全てJavaコード)でKotlinに全変換した。

その際に行った対応について。
自分のアプリの規模が小さかったからか、あまり手間がかからなかった。

---

##ターゲット

* Kotlinをなんとなく知っていて、javaで書かれたandroidアプリをkotlinに書き換えたいと思っている方。
* テストプロジェクトは対象外

---

##わたしのAndroid, Kotlin経験

* どちらも半年くらい。
    * Androidアプリはプライベートで2015/8~10頃に初めて作ってリリースした。
    * Kotlinは2016/8ごろに学んで、2016/8、2017/1頃にwebview+push通知のアプリをkotlinで書いてリリース。


---

##Kotlinに変換したアプリ

PLACE SEARCHという周辺検索アプリ。

![qiita.gif](https://qiita-image-store.s3.amazonaws.com/0/37373/b6517477-578a-121d-6414-ab3ee61a4d54.gif)

https://play.google.com/store/apps/details?id=com.hikarusato.placesearch


----

##対応工数
2日

 * Kotlinコードに書き換えて、大体の機能が動くレベルになるまで

----

##やり方

1. Android StudioにKotlinが入ってなかったら、pluginインストール。いろいろな記事にやり方があります。<br/>
   http://blog.ch3cooh.jp/entry/20160217/1455676200
2. build.gladle 編集。

```bash:build.gradle（プロジェクトの方）
buildscript {
　　　　　　　　
    ext.kotlin_version = '1.0.6'//追加
    repositories {
        jcenter()
    }
    dependencies {
        
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"//追加
    }
}
```


```bash:build.gradle（Module:appの方）
apply plugin: 'kotlin-kapt'//kotlinでアノテーションを利用できるようにする場合は追加。
apply plugin: 'kotlin-android'//追加。

・
・
・

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"//追加。
    compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"//リフレクション（プロパティ名やクラス名取得）を利用するときは追加
    testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"//テストプロジェクトを利用する場合追加
    testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"//テストプロジェクトを利用する場合追加
}
```

参考：https://kotlinlang.org/docs/reference/using-gradle.html

3.Androidプロジェクトナビゲーションで、app->javaフォルダを選択して、メインメニュー[Code]->[Convert Java File to Kotlin File]。
<img width="425" alt="スクリーンショット 2017-02-04 23.51.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/37373/20213177-49a1-96cd-7995-795eca612ae1.png">

これで、全javaコードがKotlinコードに変換される。

---

#潰したコンパイルエラー

---

#### ・NullableTypeオブジェクト.メソッド形式になっているところに !! または ? を追加。

※ Android studio 2.3 では[Convert Java File to Kotlin File]した時点で 〜!!.〜 になっている。

```java:例
        //AndroidStudioで java -> Kotlinに変換後

        mWaitDialog = ProgressDialog(this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
        //ここで、mWaitDialog!!.setMessage or 　mWaitDialog?.setMessage に変えろとエラーが出る
        mWaitDialog.setMessage(resources.getString(R.string.now_updating))
```

---

* ほとんどがこのエラー（100個以上出た）。
* 適宣、オブジェクト!!.メソッド にしたり、オブジェクト?.メソッドにしたり、に変える。<br/>
数が多いので、わたしは途中からほぼオブジェクト!!.メソッド 形式に変更しました (nullチェックはjavaコードのときにしているはずという考えで)。

---

#### ・内部クラス(internal class）内で、同じクラス内のprivateなEnumを認識できない。

```kotlin:自動変換後のkotlinコード
class A {
   private enum class TYPE {
        TYPE_1,
        TYPE_2
    }

   internal class B {
        var state = TYPE.TYPE_1//ここでenum TYPE を認識できないエラー
   }
}
```

---


```kotlin:修正後
class A {
    //private を外す
    enum class TYPE {
        TYPE_1,
        TYPE_2
    }

   internal class B {
        var state = TYPE.TYPE_1
   }
}
```

---


#### ・javaのEnum.valueOf(Enum名.class, "Enumの列挙名")が正しく変換されない

```kotlin:自動変換後のkotlinコード
    enum class TYPE {
        TYPE_1,
        TYPE_2
    }

・
・
・

    Enum.valueOf<TYPE>(TYPE::class.java!!, "Enumの列挙名")//Enum.valueOf<TYPE>でエラー
```

---

```kotlin:修正後
    enum class TYPE {
        TYPE_1,
        TYPE_2
    }

・
・
・

    TYPE.valueOf("Enumの列挙名")//Enum名.valueOf 形式に変更
```


---

##潰した実行時のエラー

---

#### ・Null, parameter favicon at 〜.onPageStarted

```kotlin:修正前

override fun onPageStarted(view: WebView, url: String, favicon: Bitmap) {

```

---

```kotlin:修正後

//faviconは nullの可能性があるので、 ? を付ける。
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {

```

---

#### ・java.lang.IllegalStateException: ViewUtils.createNaviTran…transit, enter, nextAnim) must not be null

---

```kotlin:修正前

 override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation
```


---


```kotlin:修正後
//Animationは nullの可能性があるので、 ? を付ける。
 override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation?
```


---

##kotlin変換のメリット/デメリット（所感）

---

##メリット
---

 * コード量が減る
 * 学習コストは低い。
    * 自分は、Objective-C -> Swift は一週間くらいなれなかったが、 java->kotlinは３日くらいで結構慣れた。

---

 * 標準関数が充実している。特にリスト操作系は便利（filter, map, findなど）。
 * AndroidStudioが警告でkotlinで効率的に書けるコードを教えてくれる
 * 相互利用(Kotlinからjavaコードの利用ができるし、その逆もできるので)できるので、既存のライブラリも利用できる。

---

##デメリット
---

 * 既存プロジェクトのjava -> kotlin変換の手間。
 * apkサイズが少し増える。
    * いくつかのブログで調べたところ、50KB〜800KB増えるとのことだった。
    * 自分の場合、sdkバージョンやライブラリのアップデートも行ったので参考にならないが、2.2MB(10MB->12.2MB)増えた。
 * ビルドがjavaの時より少し遅くなった気がする。

---

##まとめ

* Java -> Kotlinはそこまで大変ではなさそう。
    * Swiftのメジャーバージョンアップの方が大変な印象。
    * 今後AndroidStudioのKotlin変換精度もバージョンアップを重ねれば上がってくるはず。

---