次のような RxJava1 のコードを RxJava2 に移行することを考えます。
import rx.Observable; // RxJava1 private Value nullableValue; public Observable<Value> observeValue() { return Observable.fromEmitter(emitter -> emitter.onNext(nullableValue)) .filter(nullableValue -> nullableValue != null); }
Observable のソースとなる値は Nullable で、それを filter で null チェックをかませることで値を受け取る側は NonNull を前提にできるような感じですね。 RxJava2 では onNext() に値を渡す時点で NonNull であることを求められるため、これをそのまま RxJava2 に書き換えると実行時に例外がスローされます。
import io.reactivex.Observable; // RxJava2 private Value nullableValue; public Observable<Value> observeValue() { return Observable.create(emitter -> emitter.onNext(nullableValue)) // nullable な値を onNext には渡せない .filter(nullableValue -> nullableValue != null); // 無意味な filter になる }
ここで、nullableValue を onNext() に渡す時点で Optional*1 を使ってラップしてみると、うまく onNext には NonNull な値を渡せるようになります。 また、その後に filter と map を駆使すると、メソッドの返り値の宣言を変更することなく RxJava2 に移行できます。
import io.reactivex.Observable; // RxJava2 private Value nullableValue; public Observable<Value> observeValue() { return Observable.create(emitter -> emitter.onNext(Optional.of(nullableValue))) // Optional<Value> は NonNull .filter(Optional::isPresent) // RxJava1 での null チェックと同じ効果が得られる .map(Optional::get); // filter で値が存在することをチェックしているので安全に get できる }
Android の場合 Optional は GitHub - memoizr/retro-optional: A backport of Java8 optionals for Java7 を使うと古い OS バージョンでも利用できます。