読者です 読者をやめる 読者になる 読者になる

ついにGoogleがAndroidKotlin公式サポート👍🏻

blog.jetbrains.com

本日のGoogle I/O 2017にてGoogleAndroid開発言語としてKotlinを公式サポートすることを発表しました。 First class language、なんていい響きなんでしょう。

youtu.be

Stephanieの発表の中で突然の「One more thing…」
すると見たことのある形がパターンロックとして出現し…
f:id:lvla:20170518063159p:plain
Kotlinのロゴが!!
f:id:lvla:20170518063208p:plain
沸く会場
f:id:lvla:20170518063353p:plain
JetBrains CEOやAndrey Breslavが映し出されました。
f:id:lvla:20170518063615p:plain

その後のDeveloper向けKeynoteでもKotlinはたくさん登場しました(現在進行系で登場している)。
youtu.be

既存コードとの共存が可能であることや
f:id:lvla:20170518064153p:plain
機能の紹介
f:id:lvla:20170518064139p:plain
すでにプロダクションで利用されていることなどが話されました。
f:id:lvla:20170518064246p:plain

JetBrainsのAndrey BreslavとHadi Hariri、みんな大好きJake Wharton、PinterestのChristina LeeによるKotlinセッションの告知もされていました。
f:id:lvla:20170518064542p:plain

CyberAgentに入社しました。

2017年3月末でEurekaを退職し、4月にCyberAgentに入社しました。

誰?

前職

10ヶ月間、EurekaでPairsというデーティングサービスのAndroidアプリ開発をやってました。
ORMの移行とかアーキテクチャの刷新、新機能開発なんかをやってました。そこら辺に関しては適当にこのブログに書いてあるので興味があれば読んでみてください。

4, 5年前からあるアプリということできついコードに溢れていましたが、改善しようともがくことで色々学ぶことができました。また、大好きなKotlinの導入を受け入れてくれたチームにも感謝しています。

転職

1年も経たずにやめてしまったのでやばいことでもあったのかと聞かれます。
組織への不満は多少ありましたが、私には致命的な出来事はありませんでした。私には。

なのですぐ転職しようというよりもそのうちに転職しようくらいの温度感だったんですが、組織への不満が蓄積し始めた頃にCyberAgentから声をかけてもらい、以前から働いてみたいと思っていたので早めではありますが転職するに至りました。

前職の組織への不満はネット上に書くのは生々しいので聞きたい方はオフラインで聞いてください。

現職

f:id:lvla:20170427014831j:plain
(俺より強い奴っていうと失礼ですね、すみません。)

なぜ働いてみたかったというとこんな感じでしょうか。

  • 凄腕Androidエンジニアが多数在籍している
  • 動画を扱うプロダクトの開発をしてみたかった
  • AbemaTV, AWA, FRESH!などを見ていまの自分では作れなさそうなUIのクオリティに魅せられた
  • KotlinといえばFRESH!

そして今はFRESH!Androidアプリ開発を行っています。ちょうど今日リニューアル版がリリースされました。

今までModel層をメインに書いていたので、凝ったUIのプロダクトでViewの技術を学ぶ機会を得ることができました。また、動画を扱うプロダクトも初めてのことなのでそこら辺の技術に触れられることも楽しいです。

優秀なエンジニアが多く学ぶことが多いですし、価値に繋がるのであれば新しい技術でもガンガン導入していくスタイルなので刺激的です。

労働環境も良いです。一人あたりのワークスペース広いし、まだ行ってないけど集中部屋とかあるし、リモートワークできるので心に余裕ができました。

それではまた、どこかの勉強会で。

Mock the un-mockable Kotlin classes

f:id:lvla:20170430014523p:plain

tl;dr

  • Kotlinクラスはデフォルトfinalだからモックできない
  • Mockito2ならできるよ

Kotlinのクラス、関数はデフォルトでfinalだからモックできない。

Kotlinのクラス、関数はデフォルトfinalで継承もオーバーライドもできないのでMockitoでモックすることができません。
なので今までは以下のどれかでモック可能な状態にしていました。

  • openで継承可能、オーバーライド可能にする
  • All-open pluginでクラス/関数をすべてopenにする
  • Interfaceに切り出しておく
  • PoweMockを利用する

Mockito2.1.0でfinalでもモックできるようになった

Mockito2.1.0でMockMakerというものが導入されました。ただしMockMakerはまだ実験的段階で、デフォルトではオフになっています。
MockMakerを利用する方法は2つ用意されています。

MockMaker fileを用意する。

src/test/resources/mockito-extensionsディレクトリに以下の一行を含むorg.mockito.plugins.MockMakerファイルを置きます。

mock-maker-inline

たった一行のファイルを置くだけなのでそんなに手間ではないかな?

mockito-inlineを利用する

こちらはgradleでdependenciesを書き換えるだけです。

dependencies {
    //  testCompile "org.mockito:mockito-core:2.x.y"
    testCompile "org.mockito:mockito-inline:2.x.y"
}

どちらを利用するか

私は基本的にMockitoは直接扱っておらず、mockito-coreに依存しているKotlin向けのExtensionライブラリを利用しているのでMockMaker fileを置く方法を利用してます。

DroidKaigi 2017でWelcomeトークと2セッション行ってきた。

Welcomeトーク

なんかいつの間にかWelcomeトークでスピーカー代表として話してました!びっくり! 「当たり前と思ってる情報でも誰かにとっては需要がありますよ!プロポーザル出しましょう!」というお話をしました。 いつのまにかCodeZine, giyho.jpに載ってました。

セッション

speakerdeck.com

speakerdeck.com

Pairsで去年やったおっきな仕事の話と、僕がアプリつくるときによくやる構成の話です。
後者30分に対して詰め込みすぎたーと反省してます。
KotlinはJavaわかればかけるし(と、ヤギさんが言ってました!!!!)、RetrofitやOrmaはリポジトリのREADMEを読めばすすっと使えると思います。
問題はRxJavaとDagger2ですよね。僕も初めてのときは意味がわからなかったんですが何時間かコード書いて覚えました。
とりあえずRxJavaとDagger2の補足資料として以下を置いておきますが、どれかしらを読みながらコードを書いてみてその挙動を確かめるのが一番近道だと思います。

詳解RxJava:Scheduler、非同期処理、subscribe/unsubscribe - Qiita

ユースケースで入門するAndroid RxJava1 - Qiita

逆引きよく使うRxJava1.x オペレータ - Qiita

Dagger2 入門解説 - Qiita

サンプルアプリはこちら github.com

来年が楽しみだね

皆さんお疲れ様でした。DroidKaigi 2018が楽しみですね。

RxJava2へ段階的に移行しよう

RxJava2リリースされましたね、何ヶ月か前に。
OrmaやRetrofitがRxJava2に対応済みなので、個人的にもPairs的にもいつでも移行できる状態ではあります。

といっても大変ですよね。一体いくつのストリームがあると思ってるんですか!!
あれを全部RxJava2へ書き換えていくのはちょっと面倒ですね。できれば徐々に移行を進めていきたいところです。

RxJava1とRxJava2の相互運用

github.com そこで便利なのが、RxJavaやIxJavaの開発を行っているakarnokdさんが開発しているRxJava2Interopです。
こんな感じで相互に変換を行うことが可能です。

io.reactivex.Observable  o2 = RxJavaInterop.toV2Observabe(observable);
rx.Observable  o1 = RxJavaInterop.toV1Observable(observable, backpressureStrategy);

レイヤーごとにRxJava2に書き換えていく。

RxJava2Interopを利用すれば相互運用ができることがわかりました。 私の個人アプリやPairsではLayered Architectureを採用していますので、下の層の方(DaoやClient)から徐々にRxJava2に書き換えていけば良さそうです。

Kotlinでエレガントに

個人アプリもPairsもKotlinで開発しています。となると、

RxJavaInterop.toV2Observable(observable)

と書くのはちょっと面倒くさいな..となってきます。そこは拡張関数を利用して流れるように書きたいわけです。

observable.toV2Observable()

github.com というわけで、拡張関数を書いてまとめておきました。本家のメソッド名そのままに拡張関数を書いてるので、使い方に関しては本家をみてください。 面倒くさいのでまだJitPackつかってますがそのうちちゃんとあげます。 あとまだテストも書いてないです、そのうち書きます、またはPR待っています。

Java/Kotlin混合プロジェクトで気をつけていること。

弊社Slackの#eureka-kotlinからの転載シリーズ。 プライベートではすべてKotlinでコードを書いているのであまり気にすることがなかったのですが、pairsはJava/Kotlin混合で成り立っているのでKotlinで書いたコードがJavaからどう見えるのかを気にすることがたまにあります。 すべてを網羅しているわけではありませんが、いくつか書いてみました。

Companion object != Static

Kotlinにはstaticメソッドやstaticフィールドはありませんが、これらと同等の役割を持ったcompanion objectが存在します。

fun KotlinFragment: Fragment() {
    companion object {
        fun newInstance(...): KotlinFragment {
            ...
        }
    }
}

しかしこれをJavaから利用するには以下のようにする必要があります。

KotlinFragment.Companion.newInstance(...);

これはいまいちですね。Javaからの利用が想定される場合には@JvmStaticアノテーションを利用します。

fun KotlinFragment: Fragment() {
    companion object {
        @JvmStatic
        fun newInstance(...): KotlinFragment {
            ...
        }
    }
}
KotlinFragment.newInstance(...);

Property != Field

Kotlinで定義したPropertyはJavaからはアクセサを通して利用することになります。

class Kotlin {
    val bar = "bar"
}
kotlin.getBar();

これをJavaからFieldとして扱うためには@JvmFieldを利用します。

class Kotlin {
    @JvmField
    val bar = "bar"
}
kotlin.bar;

高階関数

Javaでは関数は第一級オブジェクトではありません。 関数を引数に取るKotlinの関数をJava8未満から利用する場合には、匿名クラスを渡す必要があります。

class Kotlin {
    fun higherOrder(func: ()->Unit) {
        ...
    }
}
kotlin.higerOrder(new Function0<Unit>() {
    @Override
    public Unit invoke() {
        return null;
    }
});

関数を返すKotlinの関数であれば、FunctionNが返ってきます。

class Kotlin {
    fun higherOreder(): ()->Unit {
        ...
    }
}
Function0<Unit> func = kotlin.higerOrder();

予約語

KotlinでJavaの予約後を使ってしまうと、Javaから呼び出すことができません。

kotlin.final()

JavaでKotlinの予約後を使った場合、Kotlinから呼び出すことはできますが扱いにくいです。

java.`is`()

open

これはJavaからの利用に限った話ではありませんが、Kotlinのクラス、関数はopenキーワードをつけなければすべてJavaでいうfinalです。
テストを書く際にmockitoを使ってKotlinクラスをモックしようとしても、継承/オーバーライドすることができません。
mockitoを利用する場合にはモック対象にopenキーワードをつけて継承/オーバーライド可能にしておきましょう。
Kotlin 1.0.6以降であればAll Openアノテーションを定義することで一括ですべてをopenにすることも可能です。

blog.jetbrains.com

KotlinのInterfaceはPropertyも定義できるんだよ

そういえば最近は仕事でもKotlinを書いています。同僚をKotlinで洗脳した甲斐があるというものです。 developers.eure.jp

しかし、全員が全員Javaを書く際と同じようにすらすらKotlinを書くことができるわけではないので、私がKotlinのTipsや文法などをつぶやくSlackのチャンネルがあり、みんなにはそれ読んでもらっています。 せっかくなのでこれからは自分のブログにも転載していこうと思います。 多少雑です。

tl;dr

  • KotlinのInterfaceはデフォルト実装を定義できる
  • KotlinのInterfaceは(バッキングフィールドを持たないものであれば)プロパティを定義できる

そういえば、(1.1からはできるが)data classは継承をサポートしてないので、デフォルト実装やpropertyをもつinterfaceを実装することで、なにかしら有効活用できそうですね。

KotlinのInterface

デフォルト実装を定義できる。

KotlinのInterfaceはJava8のInterfaceと同様に、デフォルト実装を定義できます。

interface Foo {
    fun doSomething() = "default"
}

class FooImpl : Foo {
    
}

// -------------------

val foo = FooImpl()
foo.doSomething() // return "default"

Propertyを定義できる。

JavaではInterfaceにフィールドを定義することはできませんでした。
しかし、KotlinではBacking fieldを持たないPropertyであれば定義する事ができます。

interface Foo {
    val one: Int
}

class FooImpl : Foo {
    override val one = 2
}

Backing Fieldとは

うまく説明できる気がしないのでKotlinコードと、そこから生成されるByteCodeをJavaデコンパイルしたものの対比をみて察してください。
Javaコード側でfieldの定義されているA, C, Eをbacking fieldを持ったpropertyといいます。

あわせて読みたい:

13日目:プロパティとフィールド - Kotlin Advent Calendar 2012 (全部俺)

case A

class Kotlin {
    val a = 2
}

public final class Java {
    private final int a = 2;

    public final int getA() {
       return this.a;
    }
}

case B

class Kotlin {
    val b: Int
        get() = 2
}

public final class Java {
    public final int getB() {
       return 2;
    }        
}

case C

class Kotlin {
    var c = 2
}

public final class Java {
   private int c = 2;

   public final int getC() {
      return this.c;
   }

   public final void setC(int <set-?>) {
      this.c = <set-?>;
   }
}

case D

class Kotlin {
    var d: Int
        get() = 2
        set(value) { }
}

public final class Java {
    public final int getD() {
       return 2;
    }
    
    public final void setD(int value) {
    }
}

case E

class Kotlin {
    var e: Int = 2
        set(value) { }
}

public final class Java {
   private int e = 2;

   public final int getE() {
      return this.e;
   }

   public final void setE(int value) {
   }
}