Android Retrofit请求回调触发toArray()空指针异常排查
问题根因
这个空指针崩溃没有特殊逻辑陷阱,本质是待调用toArray()方法的集合对象实际为null,结合你提到新增功能后才出现问题的背景,触发原因基本逃不过这几类:
- 修改数据实体类时调整了集合字段的映射规则,比如改了
@SerializedName的匹配值、调整了泛型声明,导致JSON解析时列表字段匹配失败,直接被赋值为null;之前功能正常是因为字段映射完全匹配,全量数据接口永远返回数组结构 - 新增搜索、饼图统计逻辑时,把之前写的前置判空逻辑删除或挪到了调用逻辑后面,拿到响应数据没做校验就直接传给列表、饼图组件处理
- 新增国家筛选功能后,请求会携带特定国家标识参数,当接口查不到对应国家的统计数据时,不会返回空数组
[],而是直接将列表字段返回为null,之前测试全量数据时没有覆盖到这个边界场景 - 漏写Retrofit响应体本身的空判断,部分异常响应码场景下
response.body()本身就是null,链式调用取内部列表字段自然拿到null值
修复步骤
- 先堵上直接崩溃点:所有集合类型变量调用类方法前,必须做空判断,用空集合做兜底,永远不要让集合变量在业务流程里持有null值
你第83行触发崩溃的代码大概率长这样:
改成带兜底校验的写法:// 错误写法:无判空直接调用集合方法 List<CovidCountry> countryList = response.body().getCountryData(); // 给饼图塞数据时直接调用toArray,countryList为null就会触发崩溃 pieChart.applyData(countryList.toArray()); adapter.submitList(countryList);// 先校验Retrofit响应本身是否合法 if (!response.isSuccessful() || response.body() == null) { showErrorTip(); return; } List<CovidCountry> countryList = response.body().getCountryData(); // 集合空值兜底 if (countryList == null) { countryList = new ArrayList<>(); } // 此时countryList永远非空,调用任何集合类方法都不会触发NPE pieChart.applyData(countryList.toArray()); adapter.submitList(countryList); - 从数据层彻底避免空集合问题:给所有实体类里的集合字段设置默认空值,JSON解析时如果对应字段不存在/返回null,会自动保留你设置的空列表,从根源上杜绝集合字段为null的情况
写法示例:public class CovidApiResponse { // 直接初始化空列表,不需要额外判空 private List<CovidCountry> countryData = new ArrayList<>(); private int globalConfirmCount; // 其余业务字段正常声明即可 } - 补全边界场景测试:专门验证搜索不存在的国家名、选择无公开数据的小众国家、网络异常返回错误响应这几个场景,确认空状态下不会崩溃,能正常展示空页面提示即可。
快速排查技巧
直接在MainActivity第83行打debug断点,触发崩溃前查看栈内的变量值,10秒就能确认到底是response.body()为null,还是body内部的列表字段为null,对应调整判空逻辑即可。
内容的提问来源于stack exchange,提问作者cuthbert
相关产品推荐
相关产品推荐

