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

为笔记应用集成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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 03:45:24