当前位置: 首页 > 知识库问答 >
问题:

RxJava toMultiMap无法使用房间数据库查询

林劲
2023-03-14

我正在尝试获取消息的地图,作者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::fromIterable),这样它可以一次发出一个项目,而不是整个列表,然后我使用“toMultiMap”进行映射

on成功方法从不被调用,我不知道这里出了什么问题。如果我不使用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 on完成}发出信号以发出累积映射。

这让我很困惑。因为Flowable类没有一个以onComplete作为参数的subscribe方法,也没有在我上面展示的第二个案例中使用它,但它仍然有效。

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

共有2个答案

罗昱
2023-03-14

您还可以使用:

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

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

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

通过阅读更多关于RxJava的信息,我了解了问题的原因。第一次通话:

messageViewModel.getAll()

正在回归

Flowable<List<Message>>

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

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

因此,解决方案是将消息ViewModel.getAll()的返回类型更改为:

Single<List<Message>>

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

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

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

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

 类似资料:
  • 我是新来的和我试图我的得到一个从它。我试图这样做的它与这是id但问题是我不知道如何返回目标从。 这就是<代码>刀 这是Repository类

  • 我转换java代码到kotlin代码,我得到类型未解决的java类错误。 我的Java类是 已转换的Kotlin类 非常感谢。

  • 错误:查询有问题:[SQLITE_ERROR]SQL错误或缺少数据库(没有这样的表:任务) 显示了这个错误,我怎么可能修复它? 我正在学习这个教程

  • 并且我发现了基于数据库版本4的可能场景的迁移varargs。 我的问题是,假设我使用的是db v1的Room,当我的应用程序到达db v10时,我将不得不编写多少迁移方法? 在sqlite中,我们在中获得已安装应用程序的当前db版本,我们只需通过开关大小写而不使用break语句,以便满足所有db升级。

  • 我在项目开发阶段。因此,我现在基本上不需要迁移。我以前有第一个表,第二个表是新添加的表。我已经预装了db。下面是使用的代码。 我还在AndroidManifest中给出了。xml。我不想使用,它也会清除我的预打包数据库。 我在emulator(API级别29)中卸载了该应用程序并运行了该应用程序。我得到了这个错误。 我不明白为什么重新安装会导致这个问题。有人能让我知道我做错了什么吗?

  • 有没有更简单的方法可以查看Android Studio中使用Room Persistence Library创建的数据库的内容?