RxJava 中相互依赖的多个 Retrofit 请求
Posted
技术标签:
【中文标题】RxJava 中相互依赖的多个 Retrofit 请求【英文标题】:Multiple Retrofit requests dependent on each other in RxJava 【发布时间】:2021-11-25 19:12:48 【问题描述】:我有三个 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 来做这样的事情吗?
【问题讨论】:
zipWith
想到了***.com/questions/30219877/…
【参考方案1】:
我确信有多种方法可以做到这一点。想到的不是超级优雅。您可以使用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,您可以创建一个“管道”到下一个flatMap
的Pair。
一旦进入最后一个flatMap
,您就可以将这对分解为locationModel
和weatherModel
,并使用它们来获取地点ID。
现在您可以轻松构建您的CityModel
。
【讨论】:
我会使用switchMap
,但我认为这些真的是Single
而不是Observable
所以是的,flatMap
也可以。
鉴于他们是改造电话,我认为源 observable 不会改变。我不明白为什么 switchMap
在这种特殊情况下会有不同的表现。
如果你假设 Observable 只发射一次,那么它的行为不会有什么不同,但如果它发射不止一次,它就会有不同。正如我在之前的评论中所说,如果只有一个发射,它们应该是 Single
我明白了。我不知道从 Retrofit 返回的 observable 会发出多个元素。也许这是可能的,我只是从来没有遇到过。我正是这个意思。在这种情况下,switchMap
不会给出与flatMap
不同的行为。确实,如果是这样的话,他们应该是Single
s【参考方案2】:
你可以试试 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) ..
【讨论】:
以上是关于RxJava 中相互依赖的多个 Retrofit 请求的主要内容,如果未能解决你的问题,请参考以下文章