RetroLambda
Java8 の ラムダ式 (Lambda Expression) の事はたぶん皆ご存知だろうが、下記の例で:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// 従来の書き方. ちょっとしたことをやりたくても長ったらしく書く必要がある
findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_LONG).show();
}
});
// Lambda Expression!!
findViewById(R.id.text).setOnClickListener(v -> Toast.makeText(this, "Hello", Toast.LENGTH_LONG).show());
}
}
上記の例でどちらで書きたいかといえば断然後者だろう。View.OnClickListener をどのように定義するか (Activity or Fragment に implements するのか、それとも無名クラスで定義するのか、フィールドに持つのか等) で悩んでいたのが馬鹿らしくなるぐらい便利だ。(上記のこの例だと ButterKnife で @OnClick
を使って定義したほうがもっと良いが)
細かい点だがラムダ式の変数のスコープが無名クラスと異なるのに注意。上記の例での this は無名クラスの方だと無名クラス自身を指しているので Activity のインスタンスを明示するのに MainActivity.this とする必要があるが、ラムダ式の中の this は ラムダ式を定義している外側の変数のスコープに対する this を指す (上記の例だと MainActivity)。
というわけで RetroLambda は積極的に使っていきたい。だが、ネット上に、Qiita 上にも RetroLambda の導入記事はいっぱいあるのだが しくじった時のエラーがめちゃくちゃ分かりにくいのでハマる。なのでもう何も考えなくても誰でも出来るように書いてみる。
前提条件として Android Studio であること。あと OS X でしか試してないので Windows だと若干異なるかもしれないが多分同じかと思われる。
1. Oracle JDK 8 が入っておりそれで Android Studio が実行されていること
まず JDK 8 が入っていないとダメなので確認する。コマンドラインから javac -version
を叩いて確認すればよい。
$ javac -version
javac 1.8.0_45
入っていない場合は Oracle のサイト からダウンロードしてインストール。
2. プロジェクト直下の build.gradle に 1 行書く
build.gradle はプロジェクト直下にあるものとモジュール直下にあるものがあるが、まずプロジェクト直下のものから。以下のように dependencies のところに 1 行追加する:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'me.tatarka:gradle-retrolambda:3.2.0' # この行を追加
}
}
allprojects {
repositories {
jcenter()
}
}
3. モジュール直下の build.gradle に 2 箇所書く
モジュール直下の build.gradle に
apply plugin: 'me.tatarka.retrolambda'
と
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
を以下のように追記する:
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda' # この行を追加
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.kojion.test"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// このブロックをまるまる追加. VERSION_1_6 や VERSION_1_7 になっていたら 1_8 に変更する
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile project(':library')
}
4. 試しにラムダ式を書いて実行してみる
上記の設定を書いたモジュールの方で
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
findViewById(R.id.text).setOnClickListener(v -> Toast.makeText(this, "Hello", Toast.LENGTH_LONG).show());
}
}
みたいなコードを書いて試しに実行してみる。OK ならばビルドが通りアプリが実行できるはず。ダメならなんか訳の分からないエラーが出るので頑張ることにする。
ライブラリプロジェクトがある場合
Android Studio のプロジェクトはモジュールを複数配置できるので、よく自前のライブラリモジュールを置いてそれを複数のプロジェクトで参照する場合があるが、ライブラリモジュールの方でラムダ式を使っている場合にはそちらの build.gradle の方にも 3. のように追記する必要がある。使っていない場合は不要だが混乱の元なので追記しておいたほうがいいだろう。