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



我在Rxjava上调用了一个谷歌位置自动完成sdk,它给我带来了一个自动完成预测列表,然后我用这个列表迭代并调用谷歌的位置详细信息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()
}

请下次提供一个合适的示例。模拟您的API是相当耗费工作的。

导入io.reactivex.rxjava3.core.Single导入org.unit.jupiter.api.测试

本例将把GoogleApi包装成一个reactive-neneneba API,它提供Single函数。为了收集List中的所有结果,可以使用Single.zip

注意:您不应该将MutableList与RxJava一起使用。总是使用不可变的数据类型,否则会遇到麻烦。

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)
}
}

备注

我没有添加observeOnsubscribeOn,因为这会增加测试的难度。请自行添加,在Single表格SearchApiImpl#search的末尾

最新更新