RxJava toMultiMap无法与会议室数据库查询一起使用

时间:2019-01-08 08:57:31

标签: android rx-java2 android-room

我正在尝试使用作者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作为参数的订阅方法,并且在上面显示的第二种情况下也没有使用它,但是它可以工作。

请帮助我,这使我发疯。

2 个答案:

答案 0 :(得分:0)

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

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

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

messageViewModel.getAll()

返回

Flowable<List<Message>>

这意味着此源将发出0到n个元素,在这种情况下为Message的“列表”。确实,它发出了Message列表,然后映射完成。但是它没有返回任何内容,因为它正在等待源中出现更多的“列表”。

您必须记住,Flowable或Observable可能会发出无限个元素。与Flowable.fromIterable的区别在于,fromIterable将停止,或者在发出作为参数传递的iterable的最后一个元素后,信号流已结束,这意味着方法序列的其余部分将不再等待更多元素,结果将返回。

因此解决方案是将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);

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

答案 1 :(得分:0)

您还可以使用:

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