第1章 Retrofit串行请求的概念与业务场景
串行请求是指多个网络请求按照严格的先后顺序依次发起:前一个请求成功并获得响应数据后,下一个请求才启动执行。这种“一个接一个”的调用模式在首屏加载中直接影响用户等待体验。
1.1 串行请求定义
在Android网络层中,串行请求意味着每条网络任务依赖上一条的结果或条件,请求链条不可并行。与之相对的是并行请求(同时发起多个独立请求)。串行请求的典型特征包括:
- 依赖链:请求B必须使用请求A的响应数据
- 顺序保证:先完成的请求不会导致后续请求提前执行
- 阻塞效应:前一个请求的延迟会累积到总加载时间
| 对比维度 | 串行请求 | 并行请求 |
|---|---|---|
| 请求启动顺序 | 逐条发起,后一条依赖前一条 | 全部同时发起 |
| 首屏总耗时 | 各请求耗时之和 | 耗时最长的请求时间 |
| 结果独立 | 后请求需要前请求数据 | 各请求无数据依赖 |
| 错误传播 | 一个失败则整个链条中断 | 单个失败不影响其他 |
1.2 首屏关键请求链
首屏加载通常包含关键请求链(Critical Request Chain):用户从点击到看见完整UI必须完成的网络请求序列。串行请求形成的链条越长,首屏白屏时间越明显。常见的关键请求链长度在2~4个层级,例如:
- 获取 → 获取用户基础信息 → 获取首页数据
- 设备注册 → 获取配置版本 → 下载远程配置
首屏优化临界点:如果一个串行链的总耗时超过1.5秒,用户感知为“等待”;超过3秒流失率会急剧上升。
1.3 典型场景:登录后拉数据
这是最常见的串行依赖场景。用户登录成功后,必须用返回的access_或user_id去请求后续的首页数据。代码实现如下(使用Retrofit + 协程模拟串行):
// 定义两个API接口
interface AuthApi {
@POST("login")
suspend fun login(@Body credentials: LoginRequest): LoginResponse
}
interface HomeApi {
@GET("home")
suspend fun getHomeData(@Header("Authorization") : String): HomeResponse
}
// 串行调用(协程内)
suspend fun loadHomeScreen() {
// 请求1:登录
val loginResponse = authApi.login(LoginRequest("user", "pass"))
// 请求2:使用登录返回的请求首页
val homeResponse = homeApi.getHomeData("Bearer ${loginResponse.accessToken}")
// 绑定UI
bindHomeView(homeResponse)
}
另一个典型场景是依赖接口:B接口的参数需要从A接口的响应中提取。例如先获取城市列表,再根据选中城市获取天气信息。这类场景中,如果串行链条过长或单个接口超时,会明显拖慢首屏加载。
1.4 串行请求链结构图
关键认知:串行请求的“首屏影响”本质上是依赖导致的顺序阻塞。理解这一概念是后续优化(如请求合并、缓存预加载、关键路径压缩)的基础。