RxJava中多个相互依赖的Retrofit请求



我有三个API调用,其中两个相互依赖。

我设置了以下端点:

interface WeatherApi {
@GET("/data/2.5/onecall")
fun getWeather(
@Query("lat") lat: Double,
@Query("lon") lon: Double,
@Query("exclude") exclude: String,
@Query("units") units: String,
@Query("appid") appKey: String
): Observable<WeatherModel>
@GET("/geo/1.0/direct")
fun getCoordinates(
@Query("q") cityName: String,
@Query("appid") appKey: String
): Observable<LocationModel>
@GET("geo/1.0/reverse")
fun getNameForLocation(
@Query("lat") lat: Double,
@Query("lon") lon: Double,
@Query("appid") appKey: String
): Observable<LocationModel>
}

interface PlacesApi {
@GET("/maps/api/place/findplacefromtext/json")
fun getPlaceId(
@Query("input") cityName: String,
@Query("inputtype") inputType: String,
@Query("fields") fields: String,
@Query("key") appKey: String
): Observable<PlacesModel>
}

我的存储库如下所示:

class WeatherRepository constructor(
private val weatherService: WeatherApi,
private val placesService: PlacesApi,
) {
fun getCoordinates(cityName: String, appKey: String) =
weatherService.getCoordinates(cityName, appKey)
fun getWeather(lat: Double, lon: Double, exclude: String, units: String, appKey: String) =
weatherService.getWeather(lat, lon, exclude, units, appKey)
fun getPlaceId(placeName: String, appKey:String) =
placesService.getPlaceId(placeName, "textquery", "photos", appKey)
}

现在在ViewModel中,我想获取所有需要的数据(三个模型)。所以我应该有一些方法,在其中我将一个接一个地执行所有三个请求,如下所示:

locationModel = weatherRepository.getCoordinates(city, BuildConfig.WEATHER_API_KEY)
weatherModel = weatherRepository.getWeather(locationModel[0].lat!!, locationModel[0].lon!!)
placesModel = weatherRepository.getPlaceId(weatherModel, BuildConfig.PLACES_API_KEY)

之后,我需要创建新的模型,其中包括所有获取的数据。比如:

val cityModel = CityModel(
locationModel,
weatherModel,
placesModel
)

有人知道如何在Kotlin中使用RxJava做这样的事情吗?

我相信有多种方法可以做到这一点。我想到的这个并不是特别优雅。您可以使用flatMap,但是您需要一路跟踪您的模型,以便您可以构建最后一个模型。您可以尝试使用Pair。

整体思路如下:

weatherRepository.getCoordinates(city, BuildConfig.WEATHER_API_KEY)
.flatMap { locationModel ->
weatherRepository.getWeather(locationModel[0].lat!!, locationModel[0].lon!!)
.map { locationModel to it }
}
.flatMap { (locationModel, weatherModel) ->
weatherRepository.getPlaceId(weatherModel, BuildConfig.PLACES_API_KEY)
.map {
CityModel(
locationModel,
weatherModel,
it
)
}
}

所以首先你getCoordinates并使用结果得到天气。使用to创建一个Pair,它被"管道化"了。进入下一个flatMap

一旦进入最后一个flatMap,您将配对解构为locationModelweatherModel,并使用它们来获取位置id。

现在你可以简单地构建你的CityModel

您可以尝试share()操作符。如下所示:

locationModelObservable = weatherRepository.getCoordinates(city, BuildConfig.WEATHER_API_KEY).share()
weatherModelObservable = locationModel.flatMap { weatherRepository.getWeather(it[0].lat!!, it[0].lon!!) }.share()
placesModelObservable = weatherModel.flatMap { weatherRepository.getPlaceId(it, BuildConfig.PLACES_API_KEY) }
zip(locationModelObservable, weatherModelObservable, placesModelObservable) { .. }

最新更新