You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中使用RxJava实现多个有依赖关系的Retrofit请求

实现方案

你可以通过RxJava的flatMap操作符处理串行依赖请求,每一步基于上一步的返回结果发起下一个请求,同时传递中间结果,最后合并为目标CityModel。

核心逻辑说明

三个请求按串行顺序执行:

  1. 第一步发起getCoordinates请求获取经纬度
  2. 第二步拿第一步返回的经纬度发起getWeather请求获取天气数据,同时携带第一步的location结果
  3. 第三步拿城市名(或前序结果里的地址信息)发起getPlaceId请求,最后把三个结果组装成CityModel

代码实现

class WeatherViewModel(
    private val weatherRepository: WeatherRepository
) : ViewModel() {
    // 管理RxJava订阅,避免内存泄漏
    private val compositeDisposable = CompositeDisposable()

    // 对外暴露的UI状态
    val cityResult = MutableLiveData<CityModel>()
    val errorMsg = MutableLiveData<String>()

    fun loadCityData(cityName: String) {
        // 第一步:获取城市经纬度
        weatherRepository.getCoordinates(cityName, BuildConfig.WEATHER_API_KEY)
            .subscribeOn(Schedulers.io())
            // 第二步:用经纬度查询天气,同时携带location结果往下传递
            .flatMap { locationList ->
                // 处理接口返回的location列表,取第一条有效数据
                val firstLocation = locationList.firstOrNull() 
                    ?: throw RuntimeException("未查询到对应城市的经纬度信息")
                weatherRepository.getWeather(
                    lat = firstLocation.lat ?: throw RuntimeException("纬度信息为空"),
                    lon = firstLocation.lon ?: throw RuntimeException("经度信息为空"),
                    exclude = "minutely,hourly", // 可根据业务需求调整过滤参数
                    units = "metric", // 单位用摄氏度,可按需调整
                    appKey = BuildConfig.WEATHER_API_KEY
                ).map { weatherModel ->
                    // 把前两步的结果配对传递
                    locationList to weatherModel
                }
            }
            // 第三步:查询placeId,合并三个结果生成CityModel
            .flatMap { (locationList, weatherModel) ->
                weatherRepository.getPlaceId(
                    placeName = cityName,
                    appKey = BuildConfig.PLACES_API_KEY
                ).map { placesModel ->
                    CityModel(
                        locationModel = locationList,
                        weatherModel = weatherModel,
                        placesModel = placesModel
                    )
                }
            }
            // 结果切换到主线程回调
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                { cityModel ->
                    cityResult.value = cityModel
                },
                { throwable ->
                    errorMsg.value = throwable.message ?: "请求失败,请稍后重试"
                }
            )
            .addTo(compositeDisposable)
    }

    override fun onCleared() {
        super.onCleared()
        // ViewModel销毁时取消所有未完成的请求
        compositeDisposable.dispose()
    }
}

注意事项

  • 若你定义的getCoordinates接口实际返回的是单个LocationModel而非列表,删除代码中firstOrNull的列表取值逻辑,直接读取locationModel的经纬度即可。
  • 上述代码替换了原示例中的!!强制非空写法,增加了空校验逻辑,避免空指针崩溃,你可以根据自己的业务模型调整校验规则。
  • 不要忘记在Activity/Fragment中观察cityResult和errorMsg来更新UI。

内容的提问来源于stack exchange,提问作者gawron103

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 04:24:04