简体   繁体   English

如何从 Rxjava 返回一个列表而不是多个发出的单曲?

[英]How can I return one list from Rxjava instead of multiple emitted singles?

I have a call to google place autocomplete sdk on a Rxjava that brings me a list of AutoCompletePredictions and then I use that list to iterate and call the place details sdk of google with that I want to return a single list with all the places details but it doesnt triggers.我在 Rxjava 上调用了 google place autocomplete sdk,它给我带来了 AutoCompletePredictions 列表,然后我使用该列表迭代并调用 google 的地点详细信息 sdk,我想返回一个包含所有地点详细信息的列表,但是它不会触发。

fun searchAutoComplete(word: String): Single<MutableList<SuggestedPlace>> {

    if (placeClient == null) {
        placeClient = this.context?.let { Places.createClient(it) }
    }
    return Observable.create<SuggestedPlace> { emiter ->
        var request = GooglePlaceHelper.getPlacesSuggestions(word)
        placeClient?.findAutocompletePredictions(request)
                ?.addOnSuccessListener { response: FindAutocompletePredictionsResponse ->
                    response.autocompletePredictions.forEach { place ->
                        var request = GooglePlaceHelper.getPlaceDetailRequest(place.placeId)
                        placeClient?.fetchPlace(request)
                                ?.addOnSuccessListener { response: FetchPlaceResponse ->
                                    val place = response.place
                                    place?.let {
                                        var suggestedPlace = SuggestedPlace(place.address!!, place.latLng?.latitude!!, place.latLng?.longitude!!)
                                        emiter.onNext(suggestedPlace)
                                    }
                                }
                    }
                }
    }.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io()).toList()

}

Please provide a proper example next time.下次请提供适当的例子。 It is quite work intensive to mock your APIs.模拟您的 API 需要大量工作。

import io.reactivex.rxjava3.core.Single import org.junit.jupiter.api.Test导入 io.reactivex.rxjava3.core.Single 导入 org.junit.jupiter.api.Test

This example will wrap the GoogleApi into a reactive -API, which provides Single functions.这个例子将把 GoogleApi 封装到一个reactive API 中,它提供了Single函数。 In order to collect all results in a List , you could use Single.zip .为了收集List中的所有结果,您可以使用Single.zip

Note: You should not use MutableList with RxJava.注意:你不应该在 RxJava 中使用MutableList Always use immutable data types, or you get into trouble.总是使用不可变的数据类型,否则你会遇到麻烦。

class So65684080 {
    @Test
    fun so65684080() {
        val googleClientStub = GoogleClientStub()

        val reactiveClient = GoogleClientReactiveImpl(googleClientStub)

        val searchApiImpl = SearchApiImpl(reactiveClient)

        searchApiImpl.search("whatever")
            .test()
            .assertValue(listOf(SuggestedPlace("fetchPlace"), SuggestedPlace("fetchPlace")))
    }
}

internal interface SearchApi {
    fun search(word: String): Single<List<SuggestedPlace>>
}

internal class SearchApiImpl(private val client: GoogleClientReactive) : SearchApi {
    override fun search(word: String): Single<List<SuggestedPlace>> {
        return client.findAutocompletePredictions("whatever")
            .flatMap { resp ->
                val fetches = resp.values.map { r -> client.fetchPlace(r) }

                Single.zip(fetches) { arr ->
                    arr.map {
                        val fetchPlaceResponse = it as FetchPlaceResponse
                        SuggestedPlace(fetchPlaceResponse.name)
                    }
                        .toList()
                }
            }
    }
}

internal interface GoogleClient {
    fun findAutocompletePredictions(request: String): Result<FindAutocompletePredictionsResponse>

    fun fetchPlace(request: String): Result<FetchPlaceResponse>
}

internal interface GoogleClientReactive {
    fun findAutocompletePredictions(request: String): Single<FindAutocompletePredictionsResponse>

    fun fetchPlace(request: String): Single<FetchPlaceResponse>
}

internal class GoogleClientStub : GoogleClient {
    override fun findAutocompletePredictions(request: String): Result<FindAutocompletePredictionsResponse> {
        return ResultStub<FindAutocompletePredictionsResponse>(FindAutocompletePredictionsResponse(listOf("fetch1", "fetch2")))
    }

    override fun fetchPlace(request: String): Result<FetchPlaceResponse> {
        return ResultStub<FetchPlaceResponse>(FetchPlaceResponse("fetchPlace"))
    }
}

internal class GoogleClientReactiveImpl(private val client: GoogleClient) : GoogleClientReactive {
    override fun findAutocompletePredictions(request: String): Single<FindAutocompletePredictionsResponse> {
        return Single.create { emitter ->
            val response: (FindAutocompletePredictionsResponse) -> Unit = {
                emitter.onSuccess(it)
            }
            client.findAutocompletePredictions(request).addOnSuccessListener(response)
            // TODO: set emitter.setCancellable {} for unsubscribing
        }
    }

    override fun fetchPlace(request: String): Single<FetchPlaceResponse> {
        return Single.create { emitter ->
            val response: (FetchPlaceResponse) -> Unit = {
                emitter.onSuccess(it)
            }
            client.fetchPlace(request).addOnSuccessListener(response)
            // TODO: set emitter.setCancellable {} for unsubscribing
        }
    }
}

internal data class SuggestedPlace(val name: String)

internal data class FetchPlaceResponse(val name: String)

internal data class FindAutocompletePredictionsResponse(val values: List<String>)

internal interface Result<T> {
    fun addOnSuccessListener(response: (r: T) -> Unit)
}

internal class ResultStub<T>(val value: T) : Result<T> {
    override fun addOnSuccessListener(response: (r: T) -> Unit) {
        response(value)
    }
}

Note笔记

I did not add observeOn and subscribeOn , because it makes testing a little more difficulty.我没有添加observeOnsubscribeOn ,因为它使测试更加困难。 Please add it by yourself, at the end of the Single form SearchApiImpl#search请自行添加,在Single form SearchApiImpl#search

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM