得到错误" Callable返回null"使用RxJava2时

时间:2017-05-03 17:59:00

标签: java android rx-java reactive-programming rx-java2

我在我的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时没有发生这种情况。

6 个答案:

答案 0 :(得分:6)

如wiki所示:

What's Different in 2.0

RxJava 2.x不再接受空值。将null作为流元素会立即导致NullPointerException,因此会调用onError方法。

这主要是为了避免因应用中的NullPointerException导致的崩溃。

我通过一种相当简单的方法解决了这个问题。 我检查了值是否为null,如果是,我用占位符对象替换了null。

还存在解决此问题的其他更复杂的方法,但对于我的用例,这种简单的方法就足够了。

答案 1 :(得分:3)

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

答案 2 :(得分:2)

我曾经有这样的代码:

null

work()可能返回Observable<R> obs = Maybe.fromCallable(this::work).toObservable(); ,正如您指出的那样,RxJava 2对此并不满意。

方法1

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

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

    e.onComplete();
});

通过这种方式,最终用户-观察者-仅在work()有任何要返回的东西时才开始。如果work()返回null,则与订阅一个空的Observer相同;什么都没发生。

方法2

Optional

方法3:

出于各种原因,将每种排放物包装成 String temp_category = "budget"; Cursor latestamount = myDb.getLatestAmount(id, temp_category); if (latestamount.getCount() == 0) { Toast.makeText(AddExpenses.this, "No amount found !", Toast.LENGTH_LONG).show(); } else { latestamount.moveToFirst(); amountfromdb_budget = latestamount.getDouble(0); } temp_category = "foodndrinks"; myDb.getLatestAmount(id, temp_category); if (latestamount.getCount() == 0) { Toast.makeText(AddExpenses.this, "No amount found !", Toast.LENGTH_LONG).show(); } else { latestamount.moveToFirst(); amountfromdb_foodndrinks = latestamount.getDouble(0); } =坏主意。

主要是因为我仅在期望的情况下在我的API中使用Optional,并且在某种“正常”情况下,有时会得到null。如果不是预期的或非常罕见的null,可能是由于同一使用者进行的另一个API调用的直接结果,那么我返回null并让使用者在这些特殊情况下进行处理,而不是让每个使用者都在整个处理Optional地方。

答案 3 :(得分:0)

您还可以将返回值包装在Optional(Java 8)中。使用optional.isPresent()和optional.get()。

在订阅中的地图

答案 4 :(得分:0)

假设在数据不可用或错误的情况下,getAlbumDetails(albumId)方法返回null,并且您愿意在这种情况下优雅地完成流,则可以使用以下方法: / p>

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

为了更好的可读性,我已经用lambda替换了匿名类,但是您可以保留它。

答案 5 :(得分:0)

我想出了这个解决方法:

首先创建了一个包装类:

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