【问题标题】:RxJava toMultiMap not working with room database QueryRxJava toMultiMap 不适用于房间数据库查询
【发布时间】:2019-06-02 22:30:56
【问题描述】:

我正在尝试使用这样的作者 ID 键获取消息映射:

Map<Long, Collection<Message>>

这是我尝试过的:

messageViewModel.getAll()
                    .flatMap(Flowable::fromIterable)
                    .toMultimap(Message::getAuthorId)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(this::onSuccess);

private void onSuccess(Map<Long, Collection<Message>> longCollectionMap) {
    Collection<Message> messages = longCollectionMap.get(0);
}

方法 messageViewModel.getAll() 返回:

Flowable<List<Message>>

然后我将它转换为 Flowable 流(Flowable::fromIterable),这样它就可以一次发出一个项目而不是整个列表,然后我使用“toMultiMap”进行映射

永远不会调用onSuccess方法,不知道这里出了什么问题。如果我不使用 toMultiMap (并对代码进行相应的修改)它可以工作,那么问题一定是 toMultiMap 方法。

但是当我尝试这个时:

List<String> list = Arrays.asList("1", "2", "3");
Flowable.fromIterable(list)
                    .toMultimap(String::length)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(this::onSuccess);

 private void onSuccess(Map<Integer,Collection<String>> integerCollectionMap) {
    Collection<String> strings = integerCollectionMap.get(1);
}

这行得通!唯一的区别是这个不调用房间数据库来获取可迭代的项目。

文档还说:

请注意,此运算符需要上游发送信号 {@code onComplete} 才能发出累积的地图。

这让我很困惑。由于 Flowable 类没有以 onComplete 作为参数的 subscribe 方法,并且它没有用于我上面展示的第二种情况,但它可以工作。

请帮帮我,这快把我逼疯了。

【问题讨论】:

    标签: android rx-java2 android-room


    【解决方案1】:

    我为遇到相同或类似问题的人找到了解决方案。

    首先,我必须调试以查看映射是否实际完成或根本没有完成。为此,我只是从 toMultiMap 方法开始调试它。然后发现其实映射已经完成了,所以问题是结果没有返回。

    阅读有关 RxJava 的更多信息后,我意识到了问题的原因。第一次调用:

    messageViewModel.getAll()
    

    回来了

    Flowable<List<Message>>
    

    这意味着该源将发出 0 到 n 个元素,在本例中为 Message 的“列表”。事实上,它发出了 Message 列表,然后映射完成。但它没有返回任何东西,因为它正在等待更多的“列表”从源头出现。

    您必须记住,Flowable 或 Observable 可能会发出无限的元素。与 Flowable.fromIterable 的不同之处在于 fromIterable 将停止,或者在发出作为参数传递的可迭代的最后一个元素后发出流结束的信号,这意味着其余的方法调用序列将不会等待更多元素来,结果将被返回。

    所以解决方案是将 messageViewModel.getAll() 的返回类型更改为:

    Single<List<Message>>
    

    所以现在它会发出 1 个项目、消息列表或错误。因此,在发出一个元素后,将不再出现,链上的其他方法将执行并返回值。

    但是“toMultiMap”方法不适用于“Single”,Single 类上没有这样的东西。所以你必须将它转换为可流动的,所以我这样做了:

    .flatMapPublisher(Flowable::fromIterable)
    

    所以最后的代码是这样的:

    messageViewModel.getAll() //Returns Single<List<Message>>
                    .flatMapPublisher(Flowable::fromIterable) // Creates a flowable from List<Message>
                    .toMultimap(Message::getAuthorId)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(this::onSuccess);
    

    非常漂亮和干净的代码,需要一些时间来理解反应式方法的工作原理,但绝对值得。希望有人觉得这很有用。

    【讨论】:

      【解决方案2】:

      你也可以使用:

      Map<Long, Collection<Message>> myMap = messageViewModel.getAll()
          .flatMap(message ->
              Observable.fromIterable(message)
                  .toMultimap(Message::getAuthorId)
                  .toObservable());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-18
        • 1970-01-01
        • 1970-01-01
        • 2021-03-18
        • 2021-11-17
        • 1970-01-01
        相关资源
        最近更新 更多