LoginSignup
33
31

More than 5 years have passed since last update.

Androidでlambdaとか

Posted at

Androidとかいうjavaっぽい何かを触っていますけど、
奴はlambdaとか使えないしlambda禁止令がどうとか以前の問題で辛いですね

ScalaでAndroidを!といってもapkのサイズは肥大化するし、多分仕事でOKでないところのほうが多いと思います


そんな昨今、retrolambdaというかなり素敵なものを教わったのでメモ

なお、QiitaにすでにAndroidでラムダ式を使いたいというエントリーが5月に上がっています

一刻も早くサンプルコード見たい人はこちら

ハマったその1

OS:Linux Mint 17 と mac OSX 10.9.4 で確認

とりあえずgradle-retrolambdaのREADMEに従えば大丈夫ですが…

retrolambdaそのものを最新(1.6.1)指定にするとコンパイルに失敗します

多分このissueあたりですかね

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileRetrolambdaDebug'.
> Process 'command '/usr/lib/jvm/java-8-oracle/bin/java'' finished with non-zero exit value 1

1.6.0指定の時は大丈夫だったので、retrolambdaConfigは指定しない(defaultの1.4.0)かコンパイルできるものを指定しましょう

その他Known Issuesは見ときましょう

とりあえず retrolambda.incremental は false にしておくのが無難なようですね

ハマったその2

AndroidStudioでいざBuildしてみたら

Execution failed for task ':app:patchAndroidJar'.
> Retrolambda: null/jre/lib/rt.jar does not exist, make sure that the environment variable JAVA_HOME or JAVA8_HOME, or the gradle property retrolambda.jdk points to a valid version of java8.

みたいなエラーががが

で、consoleでコンパイルしたら通る!みたいな。

これに関してはこちらへ

懸念点

Java6or7とJava8の2つがコンパイル環境として必要になります

gradle-retrolambdaでは
JAVA6_HOME/JAVA7_HOME/JAVA8_HOME みたいな感じでそれぞれexportしていれば楽ですけど、
例えばみんなの開発マシンにそれを強要したり、CI環境もそういう準備をしたり…という部分がちょっとハードル高いかも?

仮想環境構築もchefやansibleでらくらく!という人たちだけならなんの問題も無いでしょう。

とりあえず動かす

こんなコードが動きます。

そういやScalaでAndroidアプリ書いても、View#senOnClickListener とかには無名クラス突っ込む必要あったな…
java8様様です

view.findViewById(R.id.button1).
    setOnClickListener(v ->
        Toast.makeText(getActivity(), "test", Toast.LENGTH_LONG).show()
    );

だが物足りない

正直これだけでは物足りないと思います。

特にListの処理とか…

結局StreamApiが使えるわけではないのでよくサンプルでありそうなこんなコードを書いてもコンパイルで死にます

List<Integer> list = Arrays.asList(1,2,3,4);
Integer sum = list.stream()
    .map(i -> i * 2)
    .reduce(0,(x,y) -> x + y);
Error:(64, 31) error: cannot find symbol method stream()
Error:Execution failed for task ':app:compileDebugJava'.
> Compilation failed; see the compiler error output for details.

retrolambdaはあくまでもラムダ構文のサポートですので
もちろんそれのあるなしは大きいですけどね

でもきっとあなたのAndroidアプリにはGuavaあたりが入っていると思います

なのでこんな感じで書けるようになりますね

FluentIterable.from(Arrays.asList(1, 2, 3, 4)).
    filter(i -> i % 2 == 0).
    transform(i -> i * 2).
    toList();

new Function とか書かなくて良いし、これがAndroidで動くとは!!

すでにGuavaに依存している部分は今すぐ書き直したいですね!

View#setOnClickListenerとかがスッキリ書ける部分よりも、
こっちのほうが嬉しいところも多々ありますね!?

素晴らしい時代だ!!

だが待ってほしい

reduce/foldが無いなんて…Guavaさん信じてたのに…

ってことがよくありますよね。

このままではIntのListの合計すらままならない…

LombokのExtensionMethodで生やすか?

いやしかし…

そうだFunctionalJavaだ!

結果がこうなります

final Integer sum = fj.data.List.list(1, 2, 3, 4).
    filter(i -> i % 2 == 0).
    map(i -> i * 2).
    foldLeft(x -> y -> x + y, 0);

よく考えたらGuavaのOptionalにbindほしいなぁ…というのもFunctionalJavaを入れるだけで解決!

もう自分で追加しなくていいんだ…w

final…もめんどい

Lombokのvalを使いましょう

以下こうなる

val sum = fj.data.List.list(1, 2, 3, 4).
    filter(i -> i % 2 == 0).
    map(i -> i * 2).
    foldLeft(x -> y -> x + y, 0);

Scalaを使わずともここまで出来る時代だったのか!

IDEで赤くなるのは置いといて…w

終わりに

個人の趣味で作る分にはなんの問題も無いと思いますが、

  • retrolambdaとfunctionaljavaを入れたいんです!

ってのを周りに説得するほうが大変な気がします。

なのでこっそり足すことをオススメします(責任は取りません)

まーでもretrolambdaぐらい入れたいなぁ…

Scalaで書けるなら個人的にそっちのほうが望ましいんですけどね。

33
31
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
31