【问题标题】:RxJava: Create items in list and return new listRxJava:在列表中创建项目并返回新列表
【发布时间】:2018-10-02 07:20:55
【问题描述】:

Rx noobie here:关于如何实现这一点的任何想法?:

我有一个来自 UI 的项目列表,并希望将它们发布到服务器。我需要从服务器返回的已发布项目列表(以使用服务器发布的 ID、时间戳等)。

请原谅我的冗长示例,但这是我努力工作的代码:

/**
 * 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&lt;Maybe&lt;Item&gt;&gt; 通话成功? (或Flowable&lt;List&lt;Item&gt;&gt;,这将更接近我最终需要的)

最后,如何从一个 Flowable&lt;Maybe&lt;Item&gt;&gt;?这将有助于了解.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 *//})
}
...

【问题讨论】:

    标签: java android kotlin rx-java rx-kotlin


    【解决方案1】:

    你可以这样做:

    fun postItems(items: List<Item>): Maybe<List<Item>> {
        return items.toFlowable().map {
            postItem(it).blockingGet()
        }.toList().toMaybe()
    }
    

    但我不确定这就是你的真正意思,因为你的 Maybe 实际上不是 Maybe

    像这样更改签名会更有意义:

    fun postItems(items: List<Item>): Flowable<Maybe<Item>> {
        return items.toFlowable().map {
            postItem(it)
        }
    }
    

    【讨论】:

    • 这看起来很有希望,但是你为什么将List 转换为Flowableitems.toFlowable()...?我认为这样的方法只能在 Observable 上使用。
    • 他可能正在使用rx-kotlin(你自己用rx-kotlin标记了你的问题)。 toFlowable() 是调用Flowable.fromIterable()的扩展函数
    • 是 RxKotlin,你可以用compile 'io.reactivex.rxjava2:rxkotlin:2.3.0'添加它
    • @AlexeySoshin 我已经更新了帖子,以添加更多关于我尝试你的答案的经验的信息。感谢您的耐心:)
    • 我无法运行您的代码,但拥有return@map 似乎是错误的。通常return@ 是一个快速返回,比如break 之类的东西。我建议您尝试一次调用服务器,然后改进它以使用 map() 的调用。
    猜你喜欢
    • 1970-01-01
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多