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

Clean Architecture中嵌套请求的实现位置与性能优化疑问

问题分析与解决方案

核心结论:数据获取的编排逻辑应该留在仓库层

Clean Architecture的核心是关注点分离,仓库层的职责就是封装所有数据相关的逻辑——包括从远程/本地数据源获取数据、编排多请求的执行顺序等。ViewModel只负责处理UI状态、业务逻辑(比如把数据转成UI需要的格式)和响应用户交互,不应该掺和数据获取的具体实现。

把批量请求逻辑放在仓库层的好处:

  • 复用性:这个批量获取比赛详情的逻辑可以被多个ViewModel调用,不用重复写代码
  • 可测试性:单独测试仓库层的逻辑更简单,不用牵扯UI相关的状态
  • 职责清晰:ViewModel只需要调用仓库的方法拿到最终结果,不用关心内部怎么发起请求、怎么并行处理

优化后的仓库层代码

你原来的代码是串行发起20个请求,这就是导致应用变慢的原因。用async()+awaitAll()改成并行请求即可,同时在仓库层使用协程调度器完全合理,网络请求本来就该在Dispatchers.IO执行:

override suspend fun fetchPlayerMatches(playerId: Int): List<MatchDetails>? {
    val playerMatchesResponse = remoteDataSource.getPlayerRecentMatches(playerId)

    if (playerMatchesResponse.isSuccessful) {
        return playerMatchesResponse.body()?.let { matchesList ->
            // 用coroutineScope管理协程,确保所有请求完成后再返回,且协程取消时能联动
            coroutineScope {
                matchesList.map { matchItem ->
                    async(Dispatchers.IO) {
                        remoteDataSource.getPlayerRecentMatchesDetails(matchItem.matchId)
                    }
                }.awaitAll()
            }
        }
    }
    return null
}

为什么不建议把逻辑移到ViewModel

  • ViewModel会变得臃肿:把数据请求的编排逻辑放进去,会让ViewModel同时承担UI状态管理和数据获取的职责,违反单一原则
  • 无法复用:如果其他页面也需要同样的批量请求逻辑,得在多个ViewModel里重复写
  • 测试复杂度提升:ViewModel的单元测试需要模拟更多网络请求相关的逻辑,不如仓库层单独测试高效

额外优化建议

为了让仓库层的逻辑更易测试,可以把协程调度器通过构造函数传入,测试时替换成TestDispatcher:

class PlayerRepositoryImpl(
    private val remoteDataSource: RemoteDataSource,
    // 默认用IO调度器,测试时可传入TestDispatcher
    private val dispatcher: CoroutineDispatcher = Dispatchers.IO
) : PlayerRepository {
    override suspend fun fetchPlayerMatches(playerId: Int): List<MatchDetails>? {
        val playerMatchesResponse = remoteDataSource.getPlayerRecentMatches(playerId)

        if (playerMatchesResponse.isSuccessful) {
            return playerMatchesResponse.body()?.let { matchesList ->
                coroutineScope {
                    matchesList.map { matchItem ->
                        async(dispatcher) {
                            remoteDataSource.getPlayerRecentMatchesDetails(matchItem.matchId)
                        }
                    }.awaitAll()
                }
            }
        }
        return null
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 10:20:23