我在我的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时没有发生这种情况。
答案 0 :(得分:6)
如wiki所示:
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对此并不满意。
Observable<R> obs = Observable.create(e -> {
R r = work();
if (r != null) {
e.onNext(r);
}
e.onComplete();
});
通过这种方式,最终用户-观察者-仅在work()有任何要返回的东西时才开始。如果work()返回null,则与订阅一个空的Observer相同;什么都没发生。
Optional
出于各种原因,将每种排放物包装成 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()
})