首页 > 解决方案 > 即使数据不为空,onResponse 中的 Retrofit2 NULL 响应也是如此

问题描述

所以,我的问题相当简单。

这是我通过 API 调用得到的响应。

D/OkHttp: {"status":"error","status_code":"500","error_msg":"There was an error trying to send the password reset email."}
<-- END HTTP (220-byte body)

这是我处理电话的代码

 Call<PasswordReset> forgotPasswordCall = apiInterface.Reset(email);
    forgotPasswordCall.enqueue(new Callback<PasswordReset>() {
        @Override
        public void onResponse(Call<PasswordReset> call, Response<PasswordReset> response) {
            PasswordReset passwordReset = response.body();
            try {
                if (passwordReset.getStatusCode() != null && passwordReset.getStatusCode().equals("200")) {   //line 133
                    Log.d("Success", "Password Reset Email Sent");
                    new CustomToast().showToast(getContext(), view, "Password Email sent");
                    new LoginActivity().replaceFragment("left");
                } else {
                    String test = passwordReset.getStatusCode();
                    Log.d("Failure", test);
                    hideDialog();
                }
            }
            catch (Exception e){
                e.printStackTrace();
                hideDialog();
            }
        }

        @Override
        public void onFailure(Call<PasswordReset> call, Throwable t) {
            Log.d("Failure", "Password Reset Email Not Sent");
            new CustomToast().showToast(getContext(), view, "Email Not Sent");
            new LoginActivity().replaceFragment("left");
            hideDialog();
        }
    });

这是我遇到的例外

W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String in.siddhant.anetpays_customer.POJO.PasswordReset.getStatusCode()' on a null object reference
    at in.siddhant.anetpays_customer.Login.Fragments.ForgotPassword$1.onResponse(ForgotPassword.java:133)

如果我得到一些数据,我的回应怎么可能是空的?

PasswordReset.class

    public class PasswordReset {


    @SerializedName("data")
    private String data;
    @SerializedName("status_code")
    private String statusCode;
    @SerializedName("status")
    private String status;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public String getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(String statusCode) {
        this.statusCode = statusCode;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

改造客户

public static Retrofit getClient() {

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();


        retrofit = new Retrofit.Builder()
                .baseUrl("http://xsdf/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();



        return retrofit;

API_接口

@FormUrlEncoded
    @POST("/ddd/pwdresetrequest")
    Call<PasswordReset>Reset(@Field("email")String email);

PS - API 本身有一些问题并且总是返回"status":"error",但这不应该影响应用程序,对吧?我也很高兴分享更多代码。提前致谢。

解决方案 我根据接受的答案发布了建议的解决方案,希望它对前来寻找的人有所帮助。

forgotPasswordCall.enqueue(new Callback<PasswordReset>() {
            @Override
            public void onResponse(Call<PasswordReset> call, Response<PasswordReset> response) {
                     if (!response.isSuccessful()){
                        Gson gson = new Gson();
                        PasswordReset passwordReset1 = gson.fromJson(response.errorBody().charStream(), PasswordReset.class);
                        if (passwordReset1.getStatusCode().equals("500")){
                            new CustomToast().showToast(getContext(), view, "Password Email not sent");
                            hideDialog();
                        }
                        else {
                            Thread.dumpStack();
                            hideDialog();
                        }

                    }
                     else if (response.isSuccessful()) {
                         Log.d("Success", "Password Reset Email Sent");
                         new CustomToast().showToast(getContext(), view, "Password Email sent");
                         new LoginActivity().replaceFragment("left");
                     }

从理论上讲,retrofit2 的 onResponse 方法是在我们得到一些响应时调用,而 onFailure 在建立和接收响应的过程不满足时调用。我忽略了这个简单的事实。所以,如果有人仍然来看和阅读,我建议你也检查一下你的response.body()是否成功。快乐编码!

标签: androidjsonnullpointerexceptionretrofit2

解决方案


从改造的Response的 javadoc 中,您可以看到从成功body()响应中返回反序列化的响应。不幸的是,鉴于您似乎收到了 500,您的回复似乎不成功。

errorBody()是你想要使用的。但是,这会返回原始响应,因此您必须自己反序列化它。

有很多方法可以做到这一点。一个可能gson用于反序列化身体:

new Gson().fromJson(response.errorBody().body().string(), YourModel.class);

PS:仅仅因为你结束了onResponse它并不意味着你有一个成功的回应。但是,从您的代码看来您已经知道这一点并正在检查 http status 200


推荐阅读