狠狠撸

狠狠撸Share a Scribd company logo
Androidアプリ開発で
RxJavaを活用する
3つのユースケース
Hiroyuki Kusu ( @hkusu_ )
2016/06/23 potatotips #30
【Potatotips #30】RxJavaを活用する3つのユースケース
①非同期処理の結果うけとり
②イベントの送信/購読
③データの変更監視
※今回はデータ加工、FRP的な話はしません
※本スライド上のサンプルコードは Java 8 および
Retrolambda の利用を前提としています
①非同期処理の結果うけとり
②イベントの送信/購読
③データの変更監視
doSomethingAsnc()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aStringList -> {
// … 結果を受け取って何か
});
コールバックを廃して同期的に書ける
Observable<T>を返す非同期な処理
Observable.create(subscriber -> {
// ... 裏スレッドで何か
subscriber.onNext("something");
subscriber.onCompleted();
})
.subscribeOn(Schedulers.io()) // 裏スレッドを指定
.observeOn(AndroidSchedulers.mainThread()) // メインスレッドを指定
.subscribe(res -> {
// ... メインスレッドで結果を受け取って何か
});
ちなみに重たい処理を裏スレッドで実行させたい
時にも使える(AsyncTask、AsyncTaskLoaderの替り)
①非同期処理の結果うけとり
②イベントの送信/購読
③データの変更監視
購読側
イベント仲介用のクラス
(シングルトン)
Subject
送信側
早い話が Otto や EventBus のようなもの
コールバックを引き回すのが煩雑な場合に
(例:Activity 間の通知、ListViewの操作イベント取得など)
イベントの送信
イベントの購読
public class RxEventBus {
private final Subject<Object, Object> subject
= new SerializedSubject<>(PublishSubject.create());
public <T> Subscription onEvent(Class<T> clazz, Action1<T> handler) {
return subject
.ofType(clazz)
.subscribe(handler);
}
public void post(Object event) {
subject.onNext(event);
}
}
RxEventBus.java(前項におけるイベント仲介用のクラス)
内部にSubjectを保持
継続的にイベントを発生させるには
Subject を用いる
public class RxEventBus {
private final Subject<Object, Object> subject
= new SerializedSubject<>(PublishSubject.create());
public <T> Subscription onEvent(Class<T> clazz, Action1<T> handler) {
return subject
.ofType(clazz)
.subscribe(handler);
}
public void post(Object event) {
subject.onNext(event);
}
}
RxEventBus.java(前項におけるイベント仲介用のクラス)
イベントの購読用メソッド
イベントクラス名でフィルタ
public class RxEventBus {
private final Subject<Object, Object> subject
= new SerializedSubject<>(PublishSubject.create());
public <T> Subscription onEvent(Class<T> clazz, Action1<T> handler) {
return subject
.ofType(clazz)
.subscribe(handler);
}
public void post(Object event) {
subject.onNext(event);
}
}
RxEventBus.java(前項におけるイベント仲介用のクラス)
イベントの送信用メソッド
rxEventBus.post(new SomeEvent());
rxEventBus.onEvent(SomeEvent.class, event -> {
// … 結果を受け取って何か
});
イベントの送信
イベントの購読
イベント仲介用のクラスのインスタンスを共有(シングルトン等)し
ておけば、アプリケーションのどこからでもイベントを送れる
①非同期処理の結果うけとり
②イベントの送信/購読
③データの変更監視
データを保持するクラス
Subject購読側
購読
データ変更
public class SomeRepository {
private final Subject<String, String> subject
= new SerializedSubject<>(PublishSubject.create());
public final Observable<String> getObservable() {
return subject;
}
private void notify(String string) {
subject.onNext(string);
}
// ... 以降、CRUDのコード
}
内部にSubjectを保持
SomeRepository.java(前項におけるデータを保持するクラス)
public class SomeRepository {
private final Subject<String, String> subject
= new SerializedSubject<>(PublishSubject.create());
public final Observable<String> getObservable() {
return subject;
}
private void notify(String string) {
subject.onNext(string);
}
// ... 以降、CRUDのコード
}
SomeRepository.java(前項におけるデータを保持するクラス)
SubjectをObservable<T>
として外部へ公開
public class SomeRepository {
private final Subject<String, String> subject
= new SerializedSubject<>(PublishSubject.create());
public final Observable<String> getObservable() {
return subject;
}
private void notify(String string) {
subject.onNext(string);
}
// ... 以降、CRUDのコード
}
SomeRepository.java(前項におけるデータを保持するクラス)
データ変更を通知する
private メソッド
※データのCRUD時に notify() をコールする規則とする
someRepository.getObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aString -> {
// ... 結果を受け取って何か
});
購読側
データが変更される度にストリームが
流れてくる
データを保持するクラス
Activity/
Fragment 購読
ビューへの反映
何かしらの
CRUD操作
データ
『データに対する』ビューの描画処理が宣言的に定義できる。
データの流れが一方向なので分かりやすい
関心の分離
TIPS
?購読の一括解除ができる
?Activity の onPause() 等で購読を停止
したい場合、一度 unscribe() すると add()
できなくなる問題
? unsubscribe() でなく clear() を使う
CompositeSubscription
doSomethingAsnc()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aStringList -> {
// ... 結果を受け取って何か
});
型名を示す変数名をつけると分かりやすいかも?
Retrolambda を利用していてストリーム中
のデータの型がよく分からなくなる問題
例)List<String> の場合
public class Tuple3<T1, T2, T3> {
private final T1 t1;
private final T2 t2;
private final T3 t3;
private Tuple3(T1 t1, T2 t2, T3 t3) {
this.t1 = t1;
this.t2 = t2;
this.t3 = t3;
}
public T1 get1() {
return t1;
}
public T2 get2() {
return t2;
}
public T3 get3() {
return t3;
}
public static <T1, T2, T3> Tuple3<T1, T2, T3> create(T1 t1, T2 t2, T3 t3) {
return new Tuple3<>(t1, t2, t3);
}
}
3つ以上の時は Tuple 的なクラスを用意する
Observable<T> で複数の値を扱いたい場合
Observable<Pair<String, List<Integer>>>
2つの場合は Pair が使える
Sample code
hkusu/android-rxjava-app-sample
罢贬础狈碍厂!
予备スライド
Activity/Fragment
UseCase層
Repository層
Service層
(AndroidのServiceではない)
DI DI DI
Observable<T>
Observable<T>
Observable<T>
裏スレッド( Schedulers.io() )で実行
メインスレッド
( AndroidSchedulers
.mainThread() )で購読

More Related Content

【Potatotips #30】RxJavaを活用する3つのユースケース