android meets rxjava - 渋谷java#6
DESCRIPTION
渋谷Java#6 で発表した資料です。TRANSCRIPT
Android meets RxJava渋谷Java #6 @yo_waka
freeeという会計サービスの会社でAndroid/iOSアプリを作っています
初めまして@yo_waka 若原 祥正
本当はJavaScriptが好き
まさか複数回OOMの話しが出るようなガチなイベントだと思っ
ていませんでした><
Androidでめんどくさいこと
• 非同期なAPIを複数叩いて全て結果が揃うのを待ったり、エラー処理は1つにまとめたり
• 複数の入力値を組み合わせてチェック • これらのテスト。。。
愚直に書くとしんどいし 愚直に書くとクソコードに なりやすいところ
Androidで非同期処理の結果や 何らかの入力値のチェックを
Streamぽくシンプルに統一的に書きたい
RxJavaNetflix社が公開している
Reactive Extension
Functional Reactive Programming
については時間ないのでノータッチで
From Future to Observable
Futureは入れ子になった非同期処理の扱いがムズい、またそれぞれの結果の条件で処理を変えるとかしようとするとムズい。 (同期/非同期混じるとさらにムズい)
From Future to Observable
Observableな結果オブジェクトのフィルタ、選択、変換、結合、合成を行えるオペレーターのコレクションによって、同期/非同期を意識することなく扱えるようにする
!注)java.util.Observableではなく、rx.Observableです
Observableを返すAPI設計にすることで、様々な処理が統一的に書けるようになる
基本フロー
Observable
Publisher Observer
#create
Observable.OnSubscribe<T>#call
#subscribe
#onNext #onError #onCompleted
Observer
#call
基本フロー + 結果をフィルタ
Observable
Publisher Observer
#create
Observable.OnSubscribe<T>#call
#subscribe
#onNext #onError #onCompleted
Observer Func
#call
FailureSuccess
基本フロー + 間に処理を挟む
Observable
Publisher Observer
#create
Observable.OnSubscribe<T>#call
#subscribe
#onNext #onError #onCompleted
Observer Action
#call
Observer、Subscriber、Func、Action
全てObservableなので再利用しやすい
!A->B、C->B、D->A->C みたいな場合、 無名クラスにしなければ再利用可能
具体例
認証とユーザー情報をまとめるpublic Observable<String> login(JsonObject params) { return http.request( Request.Method.POST, API_LOGIN_URL, params ).map(new LoginFunc()).flatMap(new Func1<Token, Observable<String>>() { @Override public Observable<String> call(Token token) { return http.request( Request.Method.GET, API_USER_INFO_URL, null ); } });}!public class LoginFunc implements Func1<String, Token> { @Override public Token call(String jsonResponse) { Gson gson = GsonFactory.getSimpleInstance(); Token token = gson.fromJson(jsonResponse, Token.class); // トークンのキャッシュとか! return token; }}
レスポンスを モデルに変換
別のObservableを直列にMapする
使う側は処理を1つ書くだけ// Fragmentなどで viewModel.login(params).subscribe(new Observer<String>() { @Override public void onCompleted() {}! @Override public void onError(Throwable throwable) { // エラー処理 }! @Override public void onNext(String s) { // メインアクティビティへ遷移 startActivity(new Intent(getActivity(), MainActivity.class)); getActivity().finish(); }});
どのリクエストでエラーが 起きてもここに到達する
自作のObservableを作るpublic static Observable<String> text(TextView view) { String currentText = String.valueOf(view.getText()); final BehaviorSubject<String> subject = BehaviorSubject.create(currentText);! view.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {}! @Override public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {}! @Override public void afterTextChanged(Editable editable) { subject.onNext(editable.toString()); } });! return subject;}
入力値変更時にonNextを呼ぶ
入力値によってメニューボタンを enabled/disabledにする
Observable.combineLatest( MyObservable.text(dateInput), MyObservable.text(amountInput), new Func2<String, String>() { @Override public Boolean call(String issueDateStr, String amountStr) { long amount = NumberUtils.safeLongValueFromString(amountStr); return !Strings.isNullOrEmpty(issueDateStr) && amount > 0; } }).subscribe(new Action1<Boolean>() { @Override public void call(Boolean enabled) { menuButton.setEnabled(enabled); }});
TextInputをObservableに してシリアル連結
最後のFunc#callの返り値が引数として渡る
ここまでの結果がそれぞれ引数として入ってくる
テストもシンプルに書ける
dateInput.setText(“2014/05/31”);amountInput.setText(null);!assertThat(menuButton).isDisabled();!amountInput.setText(“50000”);!// 特にイベント発火やメソッド分割する手間もいらないassertThat(menuButton).isEnabled();
RxJava-Android
Observer、Subscriberそれぞれどのスレッドで実行するかを選択できる(重要!)。
// 別スレッドでSubscriberを実行observer.subscribeOn(Schedulers.newThread());!// メインスレッドでObserverを実行observer.observeOn(AndroidSchedulers.mainThread());
使ってみて
• 学習コストは高いけど慣れてきて上手くコンポーネント化できると楽しい
• 閲覧だけのシンプルなアプリならEventBusでもいいかも
• ちょっと複雑な入力系のアプリならおすすめ
Reactive周りが熱い
Reactive Stream JVM上のノンブロッキングなストリーム処理を標準化するプロジェクト 最終的にJSRでの標準化を目指してるらしい
Typesafe社を中心としてJVMの非同期処理周りのメインプレーヤーが勢揃いしているぽい RxJavaの作者も入ってる
せっかくなので宣伝
6月から五反田にオフィス移転するので、Android/
Gradleとかモバイルトークしたい方いればいつでも遊びに来てください! ※ 20時前後くらいに来るとご飯食べられるらしいです
ありがとうございました