为笔记应用集成Retrofit时触发空对象引用错误求助
Retrofit空指针异常:调用
DefaultResponse.getCode()时对象为null 错误日志
2023-02-25 15:15:09.576 18889-18889/exampleapp.com.notes D/AddNoteActivity: Try Catch Block Failed.... Attempt to invoke virtual method 'int tweakup.ru.notes.models.DefaultResponse.getCode()' on a null object reference
问题背景
Postman发送请求完全正常,数据库能接收数据,但APP安装到手机后仍触发上述空指针错误,Retrofit基础配置无问题。
排查与解决步骤
1. 校验DefaultResponse类与服务器响应格式的匹配度
服务器返回的JSON格式必须和实体类字段完全对应,否则Retrofit解析会失败,返回null对象。
示例Postman返回JSON:
{ "code": 200, "message": "Note added successfully" }
正确的DefaultResponse写法:
import com.google.gson.annotations.SerializedName; public class DefaultResponse { @SerializedName("code") private int code; @SerializedName("message") private String message; // 必须保留无参构造函数,Gson解析依赖它 public DefaultResponse() {} // Getter方法 public int getCode() { return code; } public String getMessage() { return message; } }
- 字段类型必须和JSON一致(如JSON中
code是数字,类中不能用String); - 用
@SerializedName显式指定字段映射,避免大小写或命名差异导致解析失败。
2. 在Retrofit回调中增加null判断
原代码大概率直接调用response.body().getCode(),未判断body是否为null。修改回调逻辑:
Call<DefaultResponse> call = api.addNote(title, content); call.enqueue(new Callback<DefaultResponse>() { @Override public void onResponse(Call<DefaultResponse> call, Response<DefaultResponse> response) { // 先判断响应是否成功,再校验body非空 if (response.isSuccessful() && response.body() != null) { int code = response.body().getCode(); // 后续业务逻辑 } else { // 打印错误信息定位问题 Log.e("AddNoteActivity", "响应失败,状态码:" + response.code()); // 打印错误响应体内容 try { if (response.errorBody() != null) { String errorContent = response.errorBody().string(); Log.e("AddNoteActivity", "错误响应体:" + errorContent); } } catch (IOException e) { e.printStackTrace(); } } } @Override public void onFailure(Call<DefaultResponse> call, Throwable t) { // 处理网络请求失败(如超时、无网络) Log.e("AddNoteActivity", "请求失败:" + t.getMessage()); t.printStackTrace(); } });
3. 配置Gson忽略未知字段
如果服务器返回的JSON包含DefaultResponse中未定义的字段,会导致Gson解析失败,返回null。修改Retrofit的Gson配置:
Gson gson = new GsonBuilder() .setLenient() // 兼容宽松的JSON格式 .excludeFieldsWithoutExposeAnnotation() // 可选,仅解析带@Expose注解的字段 .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("YOUR_BASE_URL") .addConverterFactory(GsonConverterFactory.create(gson)) .build();
4. 检查网络权限与HTTP配置
确保Manifest已添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
如果使用HTTP明文请求(非HTTPS),需在Android 9及以上配置允许明文流量:
在res/xml下创建network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>
在Manifest的application标签中引用:
<application ... android:networkSecurityConfig="@xml/network_security_config"> ... </application>
5. 打印完整响应信息
在回调中打印响应详情,确认服务器返回内容是否符合预期:
Log.d("AddNoteActivity", "状态码:" + response.code()); Log.d("AddNoteActivity", "响应消息:" + response.message()); if (response.body() != null) { Log.d("AddNoteActivity", "响应体:" + new Gson().toJson(response.body())); } else { Log.d("AddNoteActivity", "响应体为null"); }
内容的提问来源于stack exchange,提问作者Mohammed Allam
相关产品推荐
相关产品推荐

