Kotlin つまづきメモ


AndroidでKotlinをとりあえず試してみようと思い、既存のコードをKotlin変換して躓いたところをメモ。
随時アップデート予定。

# retrolambdaで書いたコードが消える

Kotlin Plugin 0.11.91 で既存コードをKotlinに変換したらretrolambdaで書いていたlambdaの中身が消えた。
少しならまた書きなおしてもいいんだけど、それなりに大きいところもありここをまた書きなおすのはちょっと辛い。
それに、RxAndroidのsubscribeは引数なしでも問題なくコンパイルが通るので、消えた部分を全部探すのはさすがに面倒。

仕方ないので、lambdaで書いていた部分を普通の無名クラスに書き換えてから変換。
build.gradleからretrolambda消し去ってから、一度ビルドすればlambdaで書いてるところがコンパイルエラーになって見つかるから楽チン(？)

# WRAP_CONTENTにアクセスできない

既存のコードをKotlinに変換したところ`LinearLayout.LayoutParams.WRAP_CONTENT`がエラーになった。
`ViewGroup.LayoutParams.WRAP_CONTENT`に変更することで無事にアクセスできた。

継承元のフィールドにはアクセス出来ないのかな？言語仕様の理解が追いついてない…

**（追記）**
Twitterでコメントもらいました。言われてみれば「継承」はしていないというのも頷ける。
@ngsw_taroさん、ありがとうございました！

<blockquote class="twitter-tweet" lang="en"><p><a href="https://twitter.com/chibatching">@chibatching</a> できませんねー。というよりもstaticなメンバはJavaでも「継承」はしていないので、最初は戸惑いがあるかも知れませんがKotlinのアプローチは理にかなっていると思います。</p>&mdash; たろう (@ngsw_taro) <a href="https://twitter.com/ngsw_taro/status/584647503884062720">April 5, 2015</a></blockquote>

# Kotlin Extensions for Android で WebView がコンパイルエラー

```
e: /ANDROIDXML10.kt: (9, 40): Unresolved reference: WebView
e: /ANDROIDXML10.kt: (9, 49): Unresolved reference: WebView
e: /ANDROIDXML10.kt: (10, 32): Unresolved reference: WebView
e: /ANDROIDXML10.kt: (12, 40): Unresolved reference: WebView
e: /ANDROIDXML10.kt: (12, 49): Unresolved reference: WebView
e: /ANDROIDXML10.kt: (13, 42): Unresolved reference: WebView
e: /ANDROIDXML11.kt: (9, 36): Unresolved reference: WebView
e: /ANDROIDXML11.kt: (9, 45): Unresolved reference: WebView
e: /ANDROIDXML11.kt: (10, 32): Unresolved reference: WebView
```

**(追記)**

解決しました！使っていたバージョンが悪かったようです…
`0.11.91`から`0.11.91.1`にアップデートすることで解決しました！

ありがとうございました！

<blockquote class="twitter-tweet" lang="en"><p><a href="https://twitter.com/chibatching">@chibatching</a> 0.11.91.1にアップデートしたら直りますよ！</p>&mdash; Yan Zhulanow (@yanex_ru) <a href="https://twitter.com/yanex_ru/status/584863244646481922">April 5, 2015</a></blockquote>

# extends と implements していたJavaクラス

Kotlinでは継承も実装もクラス名の後にカンマ区切りで書くっぽい。
そうするとJavaでextendsとimplements両方やってたクラスは継承元が2つあるように見える。

この状態で`super`を呼び出すとエラーになる。どの継承元を指すのか明示する必要がある模様。

```kotlin
public class HogeView : View, Observable.OnSubscribe<Long> {
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super<View>.onSizeChanged(w, h, oldw, oldh)
        ...
    }
```

# Proguardで失敗する

Proguardを有効にすると盛大にWarningログを吐いて失敗する。

```
...
Warning: kotlin.dom.CloseableEventListener: can't find referenced class org.w3c.dom.events.EventTarget
Warning: kotlin.dom.CloseableEventListener: can't find referenced class org.w3c.dom.events.EventListener
Warning: kotlin.dom.DomPackage: can't find referenced class org.w3c.dom.events.MouseEvent
Warning: kotlin.dom.DomPackage: can't find referenced class org.w3c.dom.events.MouseEvent
Warning: kotlin.dom.DomPackage: can't find referenced class org.w3c.dom.events.Event
Warning: kotlin.dom.DomPackage: can't find referenced class org.w3c.dom.events.Event
...
```

とりあえずWarningなので無視することにする。
この状態でビルドしたAPKでも今のところ問題は起きていない。

```
# Kotlin
-dontwarn kotlin.dom.*
-dontwarn org.w3c.dom.events.*
```

# 新しい static final なフィールド参照で落ちる

Kitkatの端末で`Build.VERSION_CODES.LOLLIPOP`を参照すると、ビルドは通るのにNo such static fieldで落ちます。
調べてみたところ、Javaではstatic finalなフィードはビルド時にインライン化されるから古い端末でも新しいAPIバージョンで追加された値が使えるが、Kotlinでは現状インライン化されていない模様。

これ地味にきつい。
バージョンコードくらいならハードコーディングするのもまあ我慢できるけど、View.SYSTEM_UI_FLAG_IMMERSIVEとか後から追加されたフラグは全部対象になってしまう。
これの影響範囲調べるのが億劫で自分のアプリのKotlin移行に躊躇してしまっている…

●該当Issue
https://youtrack.jetbrains.com/issue/KT-6724
https://youtrack.jetbrains.com/issue/KT-6818