【问题标题】:RxJava2 Iterate list and call single for every itemRxJava2 迭代列表并为每个项目调用单个
【发布时间】:2018-11-21 10:07:48
【问题描述】:

我有一个带有好友连接的数据库表:

下一个示例只是一个Imagined 示例,所以请不要建议我以其他方式实现它。

朋友连接:

  • 身份证
  • humanId

我有一个包含这些 id 的列表。

val friendConnections = arrayListOf(
    FriendConnection(id=10, humanId=141),
    FriendConnection(id=13, humanId=142)
)

我想用 RxJava 制作这个结果列表。

val friendList = arrayListOf(
    Friend(friendConnectionId = 10, humanId = 141, humanInstance = (...)),
    Friend(friendConnectionId = 13, humanId = 142, humanInstance = (...))
)

我怎样才能得到一个人?

fun getHumanById(id: Long) : Single<Human>

所以我需要迭代friendConnections 并为每个人类进行一次调用。比我需要将带有新 Human 实例的 FriendConnection 映射到 Friend 实例。

我试过了,还是不行:

Observable.fromIterable(arrayListOf(
                FriendConnection(id=10, humanId=141),
                FriendConnection(id=13, humanId=142)
        ))
                .flatMapSingle { friendConnection ->
                    repository.getHumanById(friendConnection.humanId)
                            ?.map {human ->
                                Friend(friendConnection.id,friendConnection.humanId,human)
                            }
                }
                .toList()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ it ->
                    Timber.i("friendList is here: $it")
                }, {
                    throw it 
                })

有人知道出了什么问题吗? (我想用 Rx 实现它,而不是用 Room)

【问题讨论】:

  • 你有什么结果?如果您有fun getHumanById(id: Long) : Single&lt;Human&gt; 签名,为什么在repository.getHumanById(friendConnection.humanId)?.map 中使用安全调用?
  • 为什么你想用 Rx 做这个?您可以使用 kotlin 运算符本身来实现这一点。你的repository.getHumanById 是在调用 API 吗?
  • 不,这只是一个本地数据库调用。
  • 你确定fun getHumanById(id: Long)返回Single&lt;Human&gt;而不是Single&lt;Human&gt;?(可空类型)?
  • 因为在表达式中repository.getHumanById(friendConnection.humanId)?.map {...}问号表示可以为空的类型。

标签: kotlin rx-java2


【解决方案1】:

这个解决方案适合你吗?

Observable.fromIterable(
        listOf(
            FriendConnection(1, 101),
            FriendConnection(2, 102)
        )
    )
        .flatMapSingle { connection ->
            getHumanById(connection.humanId)
                .map { human -> Friend(connection.id, connection.humanId, human) }
        }
        .toList()
        .subscribe { list -> println(list) } //method reference generates error due to methods ambiguity

通过 id 获取人类的模拟函数:

private fun getHumanById(id: Long): Single<Human> = Single.just(Human(id, id.toString()))

【讨论】:

  • 这对我不起作用。我在friendConnection 列表中有50 个项目,但只有前2 次称为flatMapSingle,为什么?
  • @vihkat,请在问题下回答我的评论。也许问题出在这里。此外,如果我们能知道它为什么不起作用,那就太酷了。编译时错误、运行时错误、意外结果?
  • 它适用于您的模拟。但不适用于我的 Single,但我确定它不会返回 null,因为我烧了一个修复 ID 女巫工作很好
  • 您完全确定 getHumanById 完全返回 Single&lt;Human&gt; 吗?它既不是Single&lt;Human?&gt; 也不是Single&lt;Human&gt;? 甚至不是Single&lt;Human?&gt;?
  • 是的。我很确定
【解决方案2】:

你可以这样做,

Observable.fromIterable(friendConnections)
        .flatMap { Observable.just(Friend(it.id, it.humanId, repository.getHumanById(it.humanId).blockingGet())) }
        .toList()
        .subscribe {it --> /*Your Operation*/

【讨论】:

  • 是的。如果repository.getHumanById 进行API 调用,那么它应该是flatMap。 (根据假设更新了答案)
  • 没有假设,方法在做什么并不重要。它返回一个 Single,因此您需要 flatMap
猜你喜欢
  • 2018-03-05
  • 2018-01-29
  • 1970-01-01
  • 2019-01-10
  • 2018-10-21
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多