【问题标题】:RxJava filtering empty list and using firstOrDefaultRxJava 过滤空列表并使用 firstOrDefault
【发布时间】:2017-09-08 11:14:09
【问题描述】:

我正在尝试过滤可能为空或不为空的列表(或该项目不在列表中)。 inboxData 被另一个 observable 填充:

private BehaviorSubject<InboxResponse> inboxData = BehaviorSubject.create();

public Observable<Item> getInboxItem(String id) {
    return inboxData
        .flatMap(response -> Observable.from(response.getData()))
        .filter(item -> item.getId().equals(id))
        .firstOrDefault(null);
}

在这种情况下,如果 response.getData() 为空 firstOrDefault 永远不会运行。但为什么?它清楚地表明,如果前面的 observable 什么都不发出,它会返回默认值。

【问题讨论】:

  • @Kiskae 的回答是正确的。另外,请注意,一旦您在BehaviorSubject 上调用onCompleted,所有后续观察者将只会收到onCompleted,而不会收到任何数据。我不确定Subject 是您在此处寻找的内容。

标签: java android list rx-java rx-java2


【解决方案1】:

firstOrDefault 如果流完成而没有任何项目通过可观察对象,则发出默认值。要让您的流完成BehaviorSubject,需要发出完成信号。由于没有迹象表明会发生这种情况,因此它永远不会意识到它需要发送默认值。

解决方案是将filterfirstOrDefault 移动到flatMap 的内部,以便getData 提供的列表末尾最终完成内部流。

请注意,如果您按照标签的建议使用 RxJava2,null 永远不会是流中的项目,因此将其作为默认值传递会导致异常。

【讨论】:

    【解决方案2】:
    public Observable<Item> getInboxItem(String id) {
        return inboxData
            .flatMap(response -> Observable.from(response.getData()))
    

    此时response.getData()返回null吧?

            .filter(item -> item.getId().equals(id))
    

    这意味着这里的item 为空。所以item.getId() 抛出一个NullPointerException。像这样的错误会立即传递给订阅者的 onError 处理程序。 firstOrDefault 方法甚至不会再被调用,因为流会立即终止。

            .firstOrDefault(null);
    }
    

    【讨论】:

    • 不,如果没有数据,response.getData() 是一个空列表
    • 我认为这与行为主体从不调用 oncomplete 有关,因此 firstOrDefault 无法调用默认部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    • 2022-01-22
    相关资源
    最近更新 更多