はじめに
@rejuspotaroさんの関数型言語を学ぶことは実務でどう役に立ったかを見てRxJavaを使ってみたくなりました。また、iOSのSwiftとAndroidのGroovyを見て、RxJavaをAndroidで使うなら、Groovyでだなと思いました。
また、上記の記事では、言及されていませんでしたがRxAndroidというものがあるようです。Viewのクリックのストリームや、EditTextの変更のストリームを生成するメソッドが用意されているみたいです。
今まで私は、RxJavaをちょっと試してみるならGroovy(これとこれ)とか、RxGroovyについて投稿していましたが、今回やっとRxAndroid、RxJavaをGroovyで使ってみたいと思います。
ボタンクリック回数を表示
ボタンクリックの回数を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は使っていないです。)
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で書いてみます。
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内の文字数を入力するたび更新し表示
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>です。
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を使ってみました。
もっと複雑なコードにもチャレンジしてみたいです。
良かったら、これもどうぞ!
- Javaのライブラリをチョロっと試すなら、Groovyで試すといいと思うんです!
- GroovyOnAndroidやRxJavaをやりたい人のための、Groovyのクロージャの書き方・使い方メモ
- RxJavaをGroovyで使う。そしてRxGroovyがやっていること(ExtensionModule)
- AndroidStudio0.6.1とGroovy2.4-beta-1で、とりあえずGroovyでAndroidアプリを作ってみた。
- 【Unityでも】UniRxを使ってみた。マウスクリックの回数を数える【リアクティブプログラミング】
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()
}