簡體   English   中英

使用 RxJava2 時出現錯誤“可調用返回空值”

[英]Getting error “Callable returned null” when using RxJava2

我在我的 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;   
       });
}

從 observable 中,我在 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 並讓消費者在這些特殊情況下處理它,而不是讓每個消費者都處理 Optional地方。

正如維基中給出的:

2.0 有什么不同

RxJava 2.x 不再接受空值。 將 null 作為流元素會立即導致NullPointerException並因此調用 onError 方法。

這樣做主要是為了避免由於應用程序中的NullPointerException而導致的崩潰。

我通過一個相當簡單的方法解決了這個問題。 我檢查了該值是否為空,如果是,我用占位符對象替換了空值。

還存在其他更復雜的方法來解決這個問題,但對於我的用例,這種簡單的方法就足夠了。

RxJava 2.x 不再接受空值而不實現錯誤處理程序

例子

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();
};

為了更好的可讀性,我已經用 lambda 替換了匿名類,但你當然可以保持原樣。

您還可以將返回值包裝在 Optional (Java 8) 中。 以及您訂閱中使用 optional.isPresent() 和 optional.get() 的地圖。

我想出了這個解決方法:

首先創建了一個包裝類:

class NullableObject<T>(val value: T?)

然后為 Single 創建了一個擴展函數,如下所示:

inline fun <T> runInSingle(
        crossinline block: () -> T,
        crossinline callback: (T?) -> Unit,
        crossinline onError: (Throwable) -> Unit) {

   Single.fromCallable {
      return@fromCallable block().toNullableObject()
   }.subscribeOn(Schedulers.io())
           .observeOn(AndroidSchedulers.mainThread())
           .subscribe { result, error ->
              if (error != null) {
                 onError(error)
              } else {
                 callback(result.value)
              }
           }
}

fun <T> T.toNullableObject(): NullableObject<T> = NullableObject(this)

如何使用 :

runInSingle({
         doSomethingInBackgroundWhichMayReturnNull()
      }, { result ->
         if(result != null) {
           doSomethingWithTheNonNullResult()
         } else {
           doSomethingWithTheNullResult()
         }
      }, { error ->
         error.printStackTrace()
      })

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM