AndroidプロジェクトでRxJava2を使用しています。
次のコードを使用してObservable
を作成しています
public Observable<AlbumDetails> loadAlbumFromAlbumId(final String albumId) {
return Observable.fromCallable(new Callable<AlbumDetails>() {
@Override
public AlbumDetails call() throws Exception {
AlbumDetails albumDetails = getAlbumDetails(albumId);
return albumDetails;
});
}
オブザーバブルから、DisposableObserverのonErrorメソッドで次のエラーが発生します
Callable returned null
これは、RxJavaを使用するときに発生しませんでした。
以前は次のようなコードがありました。
Observable<R> obs = Observable.fromCallable(this::work);
work()はnull
を返す場合があり、RxJava 2はこれに満足していません。
Observable<R> obs = Maybe.fromCallable(this::work).toObservable();
このようにして、最後のコンシューマ(オブザーバ)は、work()が返すものを持っている場合にのみ開始されます。 work()がnullを返した場合は、空のObserverをサブスクライブするのと同じです。何も起こりません。
Observable<R> obs = Observable.create(e -> {
R r = work();
if (r != null) {
e.onNext(r);
}
e.onComplete();
});
さまざまな理由により、各放出をOptional
=悪い考えにラップすること。
主に、私がAPIでOptionalを使用するのは、それが予想される場合にのみ使用するためであり、時々nullを取得する「通常の」シナリオのようなものです。同じコンシューマーによって行われた別のAPI呼び出しの直接の結果としてnullが予期されないか、非常にまれな場合は、nullを返し、すべてのコンシューマーにOptionalをすべて処理させるのではなく、コンシューマーにこれらの例外的なケースで処理させます場所。
Wikiでここに与えられているように:
RxJava 2.xはnull値を受け入れなくなりました。ストリーム要素としてnullがあると、すぐにNullPointerException
が発生し、onErrorメソッドが呼び出されます。
これは主に、アプリのNullPointerException
によるクラッシュを回避するために行われました。
私はこれをかなり単純なアプローチで解決しました。値がnullかどうかを確認し、nullの場合は、nullをプレースホルダーオブジェクトに置き換えました。
この問題に取り組む他のより洗練されたアプローチも存在しますが、私のユースケースでは、この単純なアプローチで十分でした。
RxJava 2.xは、エラーハンドラーを実装せずにnull値を受け入れなくなりました
例
Observable.fromCallable(() -> null)
.subscribe(System.out::println, Throwable::printStackTrace);
Observable.just(1).map(v -> null)
.subscribe(System.out::println, Throwable::printStackTrace);
あなたの質問者のためのソリューション
あなたが電話/サブスクライブするとき、このメソッドは以下のようにします
Observable<AlbumDetails> testObservable= Observable.create(emitter -> { ... });
testObservable.subscribe(t -> System.out.print(t),Throwable::printStackTrace);
データが利用できない場合やエラーが発生した場合にgetAlbumDetails(albumId)
メソッドがnull
を返し、そのような状況でストリームを正常に完了できると想定すると、次のようなものを使用できます。
public Observable<AlbumDetails> loadAlbumFromAlbumId(String albumId) {
return Maybe.fromCallable(() -> getAlbumDetails(albumId))
.onErrorComplete()
.toObservable();
};
読みやすくするために匿名クラスをラムダに置き換えましたが、もちろんそのままにしておくこともできます。
戻り値をオプション(Java 8)でラップすることもできます。そして、optional.isPresent()とoptional.get()を使用してサブスクリプション内でマップします。