RxJava toMultiMap 不适用于房间数据库查询

RxJava toMultiMap not working with room database Query

我正在尝试获取消息映射,作者 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() returns:

Flowable<List<Message>>

然后我将它转换为 Flowable stream(Flowable::fromIterable) 以便它可以一次发出一个项目而不是整个列表,然后我使用 "toMultiMap"[= 进行映射15=]

从来没有调用过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);
}

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

文档还说:

Note that this operator requires the upstream to signal {@code onComplete} for the accumulated map to be emitted.

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

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

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

首先,我必须进行调试以查看映射是否确实完成或根本没有完成。为此,我只是从 toMultiMap 方法开始调试它。然后发现其实是做映射的,所以问题是结果不是returning.

阅读更多关于 RxJava 的内容,我意识到了问题的原因。第一次调用:

messageViewModel.getAll()

正在 return

Flowable<List<Message>>

这意味着此源将发出 0 到 n 个元素,在本例中为 "Lists" 消息。事实上,它发出了消息列表,之后映射就完成了。但它没有 returning 任何东西,因为它正在等待更多 "Lists" 从源头上来。

你必须记住,Flowable 或 Observable 可能会发出无限元素。执行 Flowable.fromIterable 的不同之处在于 fromIterable 将停止,或者在发出作为参数传递的 iterable 的最后一个元素后发出流结束信号,这意味着方法调用序列的其余部分将不会等待更多元素出现,结果将 returned.

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

Single<List<Message>>

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

但是"toMultiMap"方法对"Single"不起作用,Single class上没有这样的东西。所以你必须把它转换成可流动的,所以我这样做了:

.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);

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

您还可以使用:

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