web-dev-qa-db-ja.com

RxJava2を使用すると「Callableがnullを返しました」というエラーが発生する

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を使用するときに発生しませんでした。

10
priyankvex

以前は次のようなコードがありました。

Observable<R> obs = Observable.fromCallable(this::work);

work()はnullを返す場合があり、RxJava 2はこれに満足していません。

方法1

Observable<R> obs = Maybe.fromCallable(this::work).toObservable();

このようにして、最後のコンシューマ(オブザーバ)は、work()が返すものを持っている場合にのみ開始されます。 work()がnullを返した場合は、空のObserverをサブスクライブするのと同じです。何も起こりません。

方法2

Observable<R> obs = Observable.create(e -> {
    R r = work();

    if (r != null) {
        e.onNext(r);
    }

    e.onComplete();
});

方法3:

さまざまな理由により、各放出をOptional =悪い考えにラップすること。

主に、私がAPIでOptionalを使用するのは、それが予想される場合にのみ使用するためであり、時々nullを取得する「通常の」シナリオのようなものです。同じコンシューマーによって行われた別のAPI呼び出しの直接の結果としてnullが予期されないか、非常にまれな場合は、nullを返し、すべてのコンシューマーにOptionalをすべて処理させるのではなく、コンシューマーにこれらの例外的なケースで処理させます場所。

9

Wikiでここに与えられているように:

2.0の相違点

RxJava 2.xはnull値を受け入れなくなりました。ストリーム要素としてnullがあると、すぐにNullPointerExceptionが発生し、onErrorメソッドが呼び出されます。

これは主に、アプリのNullPointerExceptionによるクラッシュを回避するために行われました。

私はこれをかなり単純なアプローチで解決しました。値がnullかどうかを確認し、nullの場合は、nullをプレースホルダーオブジェクトに置き換えました。

この問題に取り組む他のより洗練されたアプローチも存在しますが、私のユースケースでは、この単純なアプローチで十分でした。

7
priyankvex

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);
3
Askarc Ali

データが利用できない場合やエラーが発生した場合にgetAlbumDetails(albumId)メソッドがnullを返し、そのような状況でストリームを正常に完了できると想定すると、次のようなものを使用できます。

public Observable<AlbumDetails> loadAlbumFromAlbumId(String albumId) {
    return Maybe.fromCallable(() -> getAlbumDetails(albumId))
        .onErrorComplete()
        .toObservable();
};

読みやすくするために匿名クラスをラムダに置き換えましたが、もちろんそのままにしておくこともできます。

2
Alexander

戻り値をオプション(Java 8)でラップすることもできます。そして、optional.isPresent()とoptional.get()を使用してサブスクリプション内でマップします。