LoginSignup
61
63

More than 5 years have passed since last update.

GroovyとRxJavaとRxAndroid、シンプルなサンプルを作ってみた

Posted at

はじめに

 @rejuspotaroさんの関数型言語を学ぶことは実務でどう役に立ったかを見てRxJavaを使ってみたくなりました。また、iOSのSwiftとAndroidのGroovyを見て、RxJavaをAndroidで使うなら、Groovyでだなと思いました。

 また、上記の記事では、言及されていませんでしたがRxAndroidというものがあるようです。Viewのクリックのストリームや、EditTextの変更のストリームを生成するメソッドが用意されているみたいです。

 今まで私は、RxJavaをちょっと試してみるならGroovy(これこれ)とか、RxGroovyについて投稿していましたが、今回やっとRxAndroid、RxJavaをGroovyで使ってみたいと思います。

ボタンクリック回数を表示

click_count.png

 ボタンクリックの回数をTextViewに表示したいと思います。(ええ、分かっていますよ。Rx使う必要ないシンプルすぎる例ですね。)

ボタンクリック回数を表示用のレイアウト
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/text_view"
        android:layout_centerInParent="true"
        android:text="0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/button"
        android:layout_centerHorizontal="true"
        android:text="click"
        android:layout_alignParentBottom="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

 rx.android.observables.ViewObservableクラスのclicksメソッドを使います。引数に渡したViewのクリックストリームを作ります。(@rejuspotaroさんの記事で紹介していたサンプルでは、このViewObservable#clicks該当するメソッドを@rejuspotaroさんが自作されていました。)

 Javaでまず使ってみます。(Retrolambdaは使っていないです。)

ボタンクリック回数を表示(java)
package com.mrstar.rx_anroid;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import rx.android.events.OnClickEvent;
import rx.android.observables.ViewObservable;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.functions.Func2;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewObservable.clicks(findViewById(R.id.button))
            .map(new Func1<OnClickEvent, Integer>() {
                @Override
                public Integer call(OnClickEvent clickEvent) {
                    return 1;
                }
            })
            .scan(new Func2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer acc, Integer current) {
                    return acc + current;
                }
            })
            .subscribe(new Action1<Integer>() {
                @Override
                public void call(Integer clickCount) {
                    TextView textView = (TextView)findViewById(R.id.text_view);
                    textView.setText(clickCount.toString());
                }
            });
    }
}

 インターフェースを実装した匿名クラスのインスタンスを作るところが、かなり冗長ですね。(Retrolambdaを使えばいいのでしょうが。)

 次にGroovyで書いてみます。

ボタンクリック回数を表示(groovy)
package com.mrstar.rx_anroid

import android.app.Activity
import android.os.Bundle
import rx.android.observables.ViewObservable

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewObservable.clicks(findViewById(R.id.button))
            .map { 1 }
            .scan { acc, current -> acc + current }
            .subscribe {
                findViewById(R.id.text_view).setText(it.toString())
            }
    }
}

 すっきり!

EditText内の文字数を入力するたび更新し表示

edit_text_length.png

 EditText内に入力した文字の文字数を、TextViewに表示しようと思います。EditText内の文字列が更新されたら、TextViewの文字数も更新されます。(はい、これも別にRx使う必要は無いくらいシンプルですね。)

テキスト文字数表示用のレイアウト
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/text_view"
        android:layout_centerInParent="true"
        android:text="0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/edit_text"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>

 今度はrx.android.observables.ViewObservableクラスのtextメソッドを使います。これの返り値は、Observable<String>ではなくて、Observable<OnTextChangeEvent>です。

テキストの文字数を表示(Java)
package com.mrstar.rx_anroid;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import rx.android.events.OnTextChangeEvent;
import rx.android.observables.ViewObservable;
import rx.functions.Action1;
import rx.functions.Func1;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewObservable.text((TextView)findViewById(R.id.edit_text))
            .map(new Func1<OnTextChangeEvent, Integer>() {
                @Override
                public Integer call(OnTextChangeEvent onTextChangeEvent) {
                    return onTextChangeEvent.text.length();
                }
            })
            .subscribe(new Action1<Integer>() {
                @Override
                public void call(Integer textLength) {
                    TextView textView = (TextView)findViewById(R.id.text_view);
                    textView.setText(textLength.toString());
                }
            });
    }
}

 こちらもGroovyで書き換えます。

package com.mrstar.rx_anroid

import android.app.Activity
import android.os.Bundle

import rx.android.observables.ViewObservable

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewObservable.text(findViewById(R.id.edit_text))
            .map{ it.text.length() }
            .subscribe{
                    findViewById(R.id.text_view).setText(it.toString())
            }
    }
}

 これまた、すっきり。

まとめ

 非常に簡単な例ですが、RxJava・RxAndroidそしてGroovyを使ってみました。

 もっと複雑なコードにもチャレンジしてみたいです。

良かったら、これもどうぞ!

app/build.gradle

app/build.gradle
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.12.2'
        classpath 'me.champeau.gradle:gradle-groovy-android-plugin:0.2.+'
    }
}

apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.mrstar.rx_anroid"
        minSdkVersion 15
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    packagingOptions {
        // workaround for http://stackoverflow.com/questions/20673625/android-gradle-plugin-0-7-0-duplicate-files-during-packaging-of-apk
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/groovy-release-info.properties'
    }
}

apply plugin: 'me.champeau.gradle.groovy-android'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'io.reactivex:rxandroid:0.22.0'
    compile 'org.codehaus.groovy:groovy:2.4.0-beta-3:grooid'
    compile ('org.codehaus.groovy:groovy-json:2.4.0-beta-3') {
        transitive = false
    }
}

repositories {
    jcenter()
}
61
63
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
61
63