tkt989 🍵 ブログ

日々のメモ

CompletableとSingleが混ざった処理を行う方法

2017/11/30

public Completable connect() { /* ... */ }

public Single<Integer> getValue() { /* ... */ }

public Completable disconnect() { /* .. */ }

例えばこんなメソッドがあるとする。

何かと接続し、値を取得して切断するという処理で。呼び出す順番は必ずconnect() > getValue() > disconnect() でなければならない。

ところで、Completableをメソッドチェーンを使って直列に処理したい場合以下のようにすればいい。

connect()
  .andThen(task1())
  .andThen(task2())
  /* ... */
  .andThen(disconnect())
  .subscribe(/* ... */);

しかし、直列処理の途中でSingleが混ざったときはどのように書くのか?

toCompletable()flatMapCompletable()を使えば一応繋げられるけど、getValue()の結果を無視してしまっている。。。

connect()
  .andThen(getValue())
  .toCompletable()
  .andThen(disconnect())
  .subscribe(/* ... */);

/* ... */

connect()
  .andThen(getValue())
  .flatMapCompletable(value -> disconnect()) // valueのスコープはこのラムダ式内なのでsubscribeの中で参照できない。。。
  .subscribe(/* ... */);

どうやればいいか悩んでいたのですが、調べた結果以下のようにすればいいです。

connect()
  .andThen(getValue())
  .flatMap(value -> disconnect().andThen(Single.just(value)))
  .subscribe(value -> {
    /* ... */
  });

これでsubscribe()で値を参照することができます。

Singleのあとに複数の処理があっても、値を次々と受け渡していけばOKです。

connect()
  .andThen(getValu())
  .flatMap(value -> task1().andThen(Single.just(value)))
  .flatMap(value -> task2().andThen(Single.just(value)))
  /* ... */
  .flatMap(value -> disconnect().andThen(Single.just(value)))
  .subscribe(value -> {
    /* ... */
  });