如何在 RxJava 2.x 中处理空值?
How to handle nulls in RxJava 2.x?
假设我有
// binding dialog open to excel 2
JavaFxObservable
.actionEventsOf(importExcel2)
.map(actionEvent -> chooseFile())
.filter(Objects::nonNull)
.observeOn(Schedulers.single())
.subscribe(file -> {
sourceFile.setFile(file);
opRunner.runOp(ImportExcelTable2Op.class);
});
当文件 select 被取消并且流不允许 null
时,事实是 chooseFile()
returns null
。
那怎么办?
有两种可能的解决方案:
- 根据 return 值是否为 null,将
map
转换为对 flatMap
的调用 returns Observable.just(chooseFile())
或 Observable.empty()
.
- 编码缺失结果有
chooseFile()
returnMaybe<File>
将map
变为flatMapMaybe
。这更准确地编码了语义应该是什么。
为 Observable 创建扩展:
ObservableExt.kt
typealias Mapper<T, R> = (T) -> R?
fun <T, R> Observable<T>.mapOrEmpty(mapper: Mapper<T, R>): Observable<R> {
return this.flatMap { item ->
val mapped = mapper.invoke(item)
if (mapped != null) {
return@flatMap Observable.just<R>(mapped)
} else {
return@flatMap Observable.empty<R>()
}
}
}
用法:
任何对象:
class Profile{
var id: String? = null
var name: String? = null
}
万一:
val profile = Profile()
Observable.just(profile)
.mapOrEmpty { it.name }
假设我有
// binding dialog open to excel 2
JavaFxObservable
.actionEventsOf(importExcel2)
.map(actionEvent -> chooseFile())
.filter(Objects::nonNull)
.observeOn(Schedulers.single())
.subscribe(file -> {
sourceFile.setFile(file);
opRunner.runOp(ImportExcelTable2Op.class);
});
当文件 select 被取消并且流不允许 null
时,事实是 chooseFile()
returns null
。
那怎么办?
有两种可能的解决方案:
- 根据 return 值是否为 null,将
map
转换为对flatMap
的调用 returnsObservable.just(chooseFile())
或Observable.empty()
. - 编码缺失结果有
chooseFile()
returnMaybe<File>
将map
变为flatMapMaybe
。这更准确地编码了语义应该是什么。
为 Observable 创建扩展:
ObservableExt.kt
typealias Mapper<T, R> = (T) -> R?
fun <T, R> Observable<T>.mapOrEmpty(mapper: Mapper<T, R>): Observable<R> {
return this.flatMap { item ->
val mapped = mapper.invoke(item)
if (mapped != null) {
return@flatMap Observable.just<R>(mapped)
} else {
return@flatMap Observable.empty<R>()
}
}
}
用法:
任何对象:
class Profile{
var id: String? = null
var name: String? = null
}
万一:
val profile = Profile()
Observable.just(profile)
.mapOrEmpty { it.name }