うさがにっき

読書感想文とプログラムのこと書いてきます

Retrolamda, RxAndroidを使ったJava8っぽいAndroidコーディングはへっぽこアンドロイダーにも恩恵をもたらすのか?(Retrolamda編)

概要

Retrolamda, RxAndroidを使うことにより、Java8っぽいAndroidコーディングが可能になる
RxAndroidとRetrolambdaで大体Java8をAndroidに持ち込む - visible true

確かに導入することにより生産性の向上があると思う
だが、これまでフルスクラッチAndroidを書いていた人間に対してどうやったら学習コストを低くして導入することができるのだろうか
事実kotlinはできれば便利だけど、文法全体が変わってしまうことによりチームに導入するには難しいと感じてやめた

これを踏まえ学習コスト面から導入について記事にしていく

予定としては

  • Retrolamdaを使ったラムダ式メソッドリファレンス
  • RxAndroidを使ったoptional
  • RxAndroidを使ったStreamAPI
  • RxAndroid, Retrolamdaを使うことにより受けられる恩恵

今回はRetrolamdaを使ったラムダ式について考える

詳細

そもそもlamda式とは?

実装すべきメソッドが一つしかないインタフェースを関数型インタフェースという。
ラムダ式はこの関数型インタフェースの記述を簡単にしてくれる。

実装方法

準備

Androidで使う場合には、Java8のインストールの環境変数の設定、後はいつものgradleのビルド設定が必要になる
Java8はこちらからどうぞ
Java SE - Downloads | Oracle Technology Network | Oracle

環境変数は以下の感じでJava6のインストールした先をJAVA8_HOMEというものに設定する

$ echo $JAVA8_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home

build.gradleは以下のように

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
    }
}

apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'

android {
    compileSdkVersion 22
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "com.personal.shimadatatsuya.lamdatestproject"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.0.0'
}

実装

通常のやり方

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        
        view.findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
        
    }

lamda式を使う

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        view.findViewById(R.id.text).setOnClickListener((View lamdaView) -> {
            // 処理
        });

    }

さらに引数の型が自明の場合は型を省略することができる

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        view.findViewById(R.id.text).setOnClickListener((lamdaView) -> {
            // 処理
        });

    }

さらにさらに引数が一つだけの場合引数リストの括弧も省略可能

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        view.findViewById(R.id.text).setOnClickListener(lamdaView -> {
            // 処理
        });

    }

かなり簡潔な書き方になった
OnClickListener系はかなり使うものなのでこれのコード量が減るのは大変喜ばしい

メソッドリファレンス

匿名クラスみたいな書き方はしたくない!
クラスにonClickをまとめて書きたい!
という方はこちらを使うと吉

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        view.findViewById(R.id.text).setOnClickListener(this::onClick);

    }
    
    public void onClick(View v) {
        //処理
    }

これだとonClickListenerをfragmentにimplementsしなくてもOK