Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

はじめに

 @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()
}
RyotaMurohoshi
プログラミングが大好きで、 C#が大好きで、 .NETが大好きで、 LINQが大好きで、 JVM言語が大好きで、 ゲームで遊ぶことが大好きで、 ゲーム開発が大好きで、 頑張るのが大好きで、 Unityが大好きだったから...!
http://mrstar-memo.hatenablog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした