読者です 読者をやめる 読者になる 読者になる

うさがにっき

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

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

概要

tiro105.hateblo.jp

の続き

RxAndroidの元となったRxJavaの概念、使い方の説明と、RxJavaとRetrolamdaを組み合わせることによって更に強力になることをまとめる

詳細

RxJava

Observerパターンを拡張して、更に色々できるようにしたライブラリのこと

Observerパターン

状態変化のあるオブジェクト(Observable)に対して、それを監視するオブジェクト(Observer)を作るデザインパターン

java.utilパッケージにもObservableクラスとObserverインタフェースが定義されている
Observerインタフェースにはupdate()メソッドが定義されており、状態変化を知りたい対象にはObserverインタフェースを実装して、Observableに登録する
状態が変化した時にObserverのupdate()がcallされる・・・みたいな感じで使われる

Observable (Java Platform SE 6)
Observer (Java Platform SE 6)

RxJavaにおけるObserverパターンの実装

RxJavaには以下の要素がある

  • Observable
  • Observer / Subscribe
  • Operator

RxJavaのObserevableを作るためには監視対象オブジェクトを引数として渡す

	// fromの引数,changeObjectは変化監視対象オブジェクト
	Observable observable = Observable.from(changeObject);

changeObjectには監視対象オブジェクトが入る、例えばbuttonなら

	Observable observable = Observable.from(button);

とかになる

次にObserverを生成する、仮に監視対象をButtonとすると

	Action1<Button> observer = new Action1<Button>() {
	    @Override
	    public void call(Button button) {
	        
	    }
	};

Action1ってなんだよ、って方はjavadocを見ていただければわかるかと
RxJava Javadoc 1.0.11
引数の数によってAction10まで用意されている

最後にobservableにobserverをセットする

	observable.subscribe(observer);

これまでの説明を通しで書くとこうなる

	Observable.from(button).subscribe(new Action1<Button>() {
	    @Override
	    public void call(Button button) {
	        
	    }
	});

監視対象が変化した時にobserverで処理する前に加工したりフィルタリングしたりするのがOperator
Operatorにはかなりの種類がある
Alphabetical List of Observable Operators · ReactiveX/RxJava Wiki · GitHub

ので代表的なものだけ紹介

filter

値をフィルタリングするOperator
trueを返せばその値を採用し、falseなら捨てる
例えばButtonのテキストが設定されている時だけとかならこんな感じ

	Observable.filter(new Func1<Button, Boolean>() {
		@Override
		public Boolean call(Button button) {
			return !"".equals(button.getText());
		}
	})
map

受け取った値を変化させるOperator
例えば受け取った値を10倍している
受け取った値の型を変えることなども可能

	Observable.map(new Func1<Integer, Integer>() {
		@Override
		public Integer call(Integer i) {
			return i * 10;
		}
	})

Operatorを踏まえた全体の実装がこうなる
例えばボタンにテキストが入っている時だけ処理したいなら

	Observable.from(button)
		.filter(new Func1<Button, Boolean>() {
			@Override
			public Boolean call(Button button) {
				return !"".equals(button.getText());
			}
		})	
		.subscribe(new Action1<Button>() {
		    @Override
		    public void call(Button button) {
		        
	    }
	});

さて、ここまで書いてきて毎回匿名クラスを書くのが面倒になってくる
そこでここででてくるのが前回までやっていたletroRamdaである
letroRamdaを使って書くとこうなる

	Observable.from(button)
		.filter(button -> !"".equals(button.getText())
		.subscribe(button -> );

という感じで可読性も上がりとてもスッキリ!

RxJavaにおけるスレッドの切り替え

RxJavaではOperator, subscribeを行うスレッドを切り替えることができる
これにより重い処理はOperator, UIの変更はobserverなどのようなAsyncTaskみたいなことができる

  • subscribeOn

Operator, Observer両方のスレッドを変更する

  • ObserveOn

Observerだけのスレッドを変更する

	Observable.from(button)
		.subscribeOn(Schedulers.newThread())
		.filter(button -> !"".equals(button.getText())
		.observeOn(AndroidSchedulers.mainThread())
		.subscribe(button -> );