获取错误“;可调用的返回null“;使用RxJava2时

获取错误“;可调用的返回null“;使用RxJava2时,java,android,rx-java,reactive-programming,rx-java2,Java,Android,Rx Java,Reactive Programming,Rx Java2,我在android项目中使用RxJava2 我正在使用以下代码创建可观察的 public Observable<AlbumDetails> loadAlbumFromAlbumId(final String albumId) { return Observable.fromCallable(new Callable<AlbumDetails>() { @Override public AlbumDetails call() thro

我在android项目中使用RxJava2

我正在使用以下代码创建可观察的

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;   
       });
}
公共可观察loadAlbumFromAlbumId(最终字符串albumId){
返回Observable.fromCallable(newcallable()){
@凌驾
公共AlbumDetails调用()引发异常{
AlbumDetails AlbumDetails=getAlbumDetails(albumId);
返回详细信息;
});
}
从可观察的角度来看,我在一次性观察者的onError方法中得到以下错误

Callable返回空值


这在使用RxJava时不会发生。

如wiki中所示:


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

这样做主要是为了避免由于应用程序中的
NullPointerException
而导致崩溃

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


其他更复杂的方法也可以解决这个问题,但对于我的用例来说,这种简单的方法已经足够了。

rxjava2.x不再接受空值而不实现错误处理程序

示例

Observable.fromCallable(() -> null)
    .subscribe(System.out::println, Throwable::printStackTrace);

Observable.just(1).map(v -> null)
    .subscribe(System.out::println, Throwable::printStackTrace);
针对您的问题的解决方案

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);
Observable testObservable=Observable.create(发射器->{…});
testObservable.subscribe(t->System.out.print(t),Throwable::printStackTrace);

您还可以将返回值包装在可选的(Java 8)中,并使用Optional.isPresent()和Optional.get()将其映射到订阅中。

我以前有这样的代码:

Observable<R> obs = Observable.fromCallable(this::work);
public Observable<AlbumDetails> loadAlbumFromAlbumId(String albumId) {
    return Maybe.fromCallable(() -> getAlbumDetails(albumId))
        .onErrorComplete()
        .toObservable();
};
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)
这样,最终消费者——观察者——只有在work()返回任何内容时才会启动。如果work()返回null,则与订阅空观察者相同;什么也不会发生

方法2
Observable obs=可观测的。创建(e->{
R=功();
如果(r!=null){
e、 onNext(r);
}
e、 onComplete();
});
方法3: 将每个排放包装在一个
可选的
=坏主意,原因有很多


主要是因为我只在我的API中使用可选的,若它是预期的,并且有点“正常”场景是,您不时会得到一个null。如果null不是预期的或非常罕见,可能是由于同一消费者执行的另一个API调用的直接结果,那么我返回null,让消费者在这些异常情况下处理它,而不是让每个消费者处理所有可选的问题。

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

Observable<R> obs = Observable.fromCallable(this::work);
public Observable<AlbumDetails> loadAlbumFromAlbumId(String albumId) {
    return Maybe.fromCallable(() -> getAlbumDetails(albumId))
        .onErrorComplete()
        .toObservable();
};
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)
公共可观察loadAlbumFromAlbumId(字符串albumId){
返回Maybe.fromCallable(()->getAlbumDetails(albumId))
.onErrorComplete()
.toObservable();
};

为了更好的可读性,我用lambda替换了匿名类,但您当然可以保持原样。

我提出了以下解决方法:

首先创建了一个包装器类:

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

在编译时不给出错误,在调试apk中也不给出错误,但让您尝试一下已发布的apk。