Rx noobie здесь: есть идеи, как этого добиться?:
У меня есть список элементов из пользовательского интерфейса, и я хотел бы разместить их на сервере.Мне нужен список POST-элементов, возвращаемых с сервера (чтобы использовать выданные сервером идентификаторы, временные метки и т. Д.).
Извините за длинные примеры, но вот код, который я изо всех сил стараюсь заставить работать:
/**
* create each item (POST) in the list and return the list
* of newly created ones
*/
fun postItems(items: List<Item>): Maybe<List<Item>> {
// loop through all items, making a network call for each and return the
// list of POSTed items
// attempt 1
// Failed type inference. Expected type mismatch:
// Expected: Maybe<List<Item>>
// Found: List<Maybe<Item>>
return items.map {
postItem(it)
}
// attempt 2: 'extract' each item in resulting observable and
// shove it back to original list
return Maybe.just(items.map {
postItem(it!!)
// 'extract' item from observable
.flatMap {
// error: Type mismatch.
// Required ((Item) -> MaybeSource<out (???...???)>!)!
// Found (Item) -> Item
it
}
})
// attempt 3: convert a Maybe to Flowable to collect all items from post
// and emit them as a single list
// Type mismatch. Required:(((Mutable)List<Item!>) -> SingleSource<out (???...???)>!)!
// Found: ((Mutable)List<Item!>) -> (Mutable)List<Item!>
return items.forEach {
postItem(it!!).toFlowable().toList().flatMap { it }
}
// attempt 4: modify attempt 3 with concatMap:
// Type mismatch. Required:((List<Item!>) -> MaybeSource<out (???...???)>!)!
// Found: (List<Item!>) -> List<Maybe<Item>>
return Maybe.just(items)
// wait for each observable to finish all the work
// until the next one is processed
.concatMap({
it.map { addItem(it!!) }
}).toFlowable()
.toList().toMaybe()
// attempt 6: blocking call on each API request.
// results in android.os.NetworkOnMainThreadException
return Maybe.just(places.map {
addPlace(it!!).blockingGet()
})
}
fun postItem(item: Item): Maybe<Item> {
return networkService.post(item) // async call to API, returns Maybe<Item>
}
ОБНОВЛЕНИЕ
Я попробовал подход, предложенный @AlexeySoshin ниже, но все еще есть некоторые моменты путаницы:
Я попробовал второй, более короткий подходно вызов дооснащения не происходит по какой-то причине :(, то есть конечные точки сетевых служб не затронуты).Он немного изменен, потому что я не смог заставить работать оболочку rx-kotlin, но я предполагаю, что это примерно эквивалентно этому:
fun addItems(items: List<Item?>): Flowable<Maybe<Item>> {
return Flowable.fromIterable(items).map {
// tried items.toFlowable().map but got 'Unresolved reference toFlowable
// even after adding rx-kotlin to project via gradle
return@map postItem(it)
}
}
Моя сетевая служба успешно работает для одного элемента с этим кодом:
// works as expected
fun postOneItem(item: Item): Maybe<Item> {
return postItem(item)
}
// also works
fun postOneItemFlowable(item: Item): Flowable<Item> {
return postItem(item).toFlowable()
}
// this variant didn't work
fun postOneItemFlowable(item: Item): Flowable<Maybe<Item>> {
return Flowable.just(postItem(item))
}
Как сделать так, чтобы Flowable<Maybe<Item>>
звонки проходили успешно?(или Flowable<List<Item>>
, что в конечном итоге было бы ближе к тому, что мне нужно)
Наконец, как получить фактический список вывода из Flowable<Maybe<Item>>
?Было бы полезно увидеть, как блок .subscribe()
может выглядеть, чтобы «извлечь» этот окончательный список.Вот как выглядит мой текущий код подписки:
...
private fun createItem(item: Item) {
disposables.add(
addItemUseCase.postOneItem(item)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
Timber.d("one item posted: $it")
}, { /* error handler *//})
}
...