我有一个问题,到目前为止我无法解决 我是RxKotlin的新手,所以这可能很容易。请看一下代码:
override fun infos(): Stream<Info> =
client.infoAboutItem(identifier)
.map {
val itemId = it.itemId ?: ""
val item = client.itemForId(itemId)
ClientInfo(client, it, source, item) as Info
}
.let { AccessStream(it) }
stream是我们自制的系列。 Map是一种允许您迭代该集合中的每个项目的方法。
这里的问题是
client.itemForId(itemId)
是一个http调用,它返回一个不理想的Single。
我想在map中创建一个异步调用,它将返回Item而不是Single,然后将其传递给ClientInfo。我到目前为止尝试过的事情是在地图中使用subscribe并使用blockingGet()方法,但即使我在不同的线程上观察和订阅,这也会阻止主线程
因此它涉及对集合中的每件事进行异步调用。
感谢您的帮助
答案 0 :(得分:1)
您可以尝试返回Observable<Stream<Info>>
,然后看起来像:
override fun infos(): Observable<Stream<Info>> =
Observable.from(client.infoAboutItem(identifier))
.flatMapSingle {
val itemId = it.itemId ?: ""
client.itemForId(itemId)
}
.map {
ClientInfo(client, it, source, item) as Info
}
.toList()
.flatMap {
AccessStream(it)
}
答案 1 :(得分:0)
您应该将这些昂贵的操作包装到observable中,并使用平面地图将这些数据压缩到客户端信息中。
我写了一个小样本来展示它。
class SimpleTest {
val testScheduler = TestScheduler()
@Test
fun test() {
infos().observeOn(Schedulers.immediate())
.subscribe { logger("Output", it.toString()) }
testScheduler.advanceTimeBy(10, TimeUnit.MINUTES)
}
fun infos(): Single<List<ClientInfo>> {
return Observable.from(infoAboutItem("some_identifier"))
.doOnNext { logger("Next", it.toString()) }
.flatMap { aboutItem ->
Observable.fromCallable { itemForId(aboutItem.itemId) }
.subscribeOn(testScheduler)
.map { ClientInfo(aboutItem = aboutItem, item = it) }
}
.doOnNext { logger("Next", it.toString()) }
.toList()
.toSingle()
}
data class ClientInfo(
val id: String = UUID.randomUUID().toString(),
val aboutItem: AboutItem,
val item: Item
)
data class AboutItem(val itemId: String = UUID.randomUUID().toString())
data class Item(val id: String = UUID.randomUUID().toString())
fun infoAboutItem(identifier: String): List<AboutItem> {
return (1..10).map { AboutItem() }
}
fun itemForId(itemId: String): Item {
val sleepTime = Random().nextInt(1000).toLong()
Thread.sleep(sleepTime)
return Item()
}
fun logger(tag: String, message: String): Unit {
val formattedDate = Date(Schedulers.immediate().now()).format()
System.out.println("$tag @ $formattedDate: $message")
}
fun Date.format(): String {
return SimpleDateFormat("HH:mm:ss.SSS", Locale.US).format(this)
}
}