Retrofit调用API返回Null数据,请求技术排查帮助
问题排查与解决方案
核心问题分析
- API返回结构不匹配
目标APIhttps://dummy.restapiexample.com/api/v1/employees的返回是包含外层包装的JSON对象,而非直接的员工列表。实际返回格式如下:
{ "status": "success", "data": [{"id":1, "employee_name":"Tiger Nixon", ...}, ...], "message": "Successfully! All records has been fetched." }
你当前的ApiService直接返回List<Employee>,Gson无法解析这种嵌套结构,导致返回null或静默解析失败。
Model类字段兼容性问题
API中profile_image字段可能返回空字符串或null,但你的Employee类将其定义为非空String,若遇到null值会触发解析异常,进而导致数据无法正常获取。异常处理与状态更新缺失
catch块仅打印异常栈轨迹,未更新状态流。若请求或解析失败,UI会一直停留在加载状态,无法感知错误。
修复步骤
1. 添加外层响应Model类
创建对应API返回结构的包装类:
data class EmployeeResponse( val status: String, val data: List<Employee>, val message: String )
2. 修改ApiService接口
调整返回类型为外层包装类,并修正请求路径(去掉开头斜杠,避免与baseUrl冲突):
interface ApiService { @GET("api/v1/employees") suspend fun getEmployees(): EmployeeResponse }
3. 调整Employee类字段可空性
给可能为空的字段添加可空标记或默认值:
data class Employee( val id: Int, val employee_name: String, val employee_salary: Int, val employee_age: Int, val profile_image: String? = "" // 设为可空或默认空字符串 )
4. 修正ViewModel数据解析逻辑
在fetchData中正确提取外层响应里的员工列表,并完善异常处理:
private fun fetchData() { viewModelScope.launch { try { // 建议将Retrofit实例改为单例(如用依赖注入或全局对象),避免重复创建 val apiService = Retrofit.Builder() .baseUrl("https://dummy.restapiexample.com/") .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiService::class.java) val response = apiService.getEmployees() _data.value = response.data // 提取嵌套的员工列表 } catch (e: Exception) { e.printStackTrace() _data.value = emptyList() // 失败时更新状态,告知UI } } }
5. 优化UI状态判断
调整EmployeeScreen的状态逻辑,更清晰区分加载、空数据、正常数据状态:
@Composable fun EmployeeScreen(viewModel: EmployeeViewModel) { val data by viewModel.data.collectAsState(initial = null) when { data == null -> CircularProgressIndicator() // 加载中 data.isEmpty() -> Text(text = "无数据或加载失败") else -> LazyColumn { items(data) { employee -> EmployeeListItem(employee) } } } }
内容的提问来源于stack exchange,提问作者Shubhankar Pande
相关产品推荐
相关产品推荐

