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

Android Studio模板Login Activity中Retrofit2 API错误处理问询

解决Retrofit2登录场景下错误响应(200状态码)导致的程序崩溃问题

你遇到的核心问题是服务器返回错误信息时HTTP状态码仍然是200,导致Retrofit默认将其判定为成功响应,强行解析成LoggedInUser对象,最终因为解析出空对象或无效数据,在LoginRepository保存用户信息时触发空指针异常(NPE)。下面是具体的解决方案:

步骤1:创建错误响应实体类

首先根据服务器返回的错误格式,定义对应的实体类用于解析错误信息:

public class ApiErrorResponse {
    private String erreur;
    private String statut;

    // Getter方法
    public String getErreur() {
        return erreur;
    }

    public String getStatut() {
        return statut;
    }
}

步骤2:修改Retrofit接口与数据源处理逻辑

由于服务器成功和错误响应的结构完全不同,我们需要让Retrofit先返回原始的ResponseBody,再手动判断解析类型。

调整Retrofit接口

把原来返回Call<LoggedInUser>的接口改为返回Call<ResponseBody>:

public interface AuthApiService {
    @POST("你的登录接口路径")
    Call<ResponseBody> login(@Field("username") String username, @Field("password") String password);
}

更新DataSource的login方法

在数据源中手动解析响应体,区分成功和错误场景:

public Result<LoggedInUser> login(String username, String password) {
    try {
        Response<ResponseBody> response = authApiService.login(username, password).execute();
        if (response.isSuccessful()) {
            String rawResponse = response.body().string();
            Gson gson = new Gson();

            // 先尝试解析为成功的用户对象
            try {
                LoggedInUser loggedInUser = gson.fromJson(rawResponse, LoggedInUser.class);
                // 验证用户对象是否有效(根据你的LoggedInUser结构调整判断逻辑)
                if (loggedInUser != null && loggedInUser.getUserId() != null) {
                    return new Result.Success<>(loggedInUser);
                }
                // 用户对象无效,尝试解析错误响应
                ApiErrorResponse errorResponse = gson.fromJson(rawResponse, ApiErrorResponse.class);
                return new Result.Error(new Exception(errorResponse.getErreur()));
            } catch (JsonSyntaxException e) {
                // 解析用户失败,确认是错误响应
                ApiErrorResponse errorResponse = gson.fromJson(rawResponse, ApiErrorResponse.class);
                String errorMsg = errorResponse != null ? errorResponse.getErreur() : "Connexion échouée";
                return new Result.Error(new Exception(errorMsg));
            }
        } else {
            // 处理HTTP状态码非200的异常情况
            return new Result.Error(new Exception("Erreur serveur : Code " + response.code()));
        }
    } catch (IOException e) {
        // 处理网络异常
        return new Result.Error(new Exception("Erreur réseau, veuillez réessayer", e));
    }
}

步骤3:确保LoginRepository逻辑正常工作

现在你的LoginRepository中的login方法可以正确区分Result.Success和Result.Error,不会再因为错误响应进入成功分支去保存空用户对象:

public Result<LoggedInUser> login(String username, String password) {
    Result<LoggedInUser> result = dataSource.login(username, password);
    if (result instanceof Result.Success) {
        // 只有真正成功时才保存用户信息,彻底避免NPE
        setLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
    }
    return result;
}

关键思路说明

  • 服务器错误返回200状态码打破了Retrofit默认的"成功=2xx状态码"逻辑,因此必须手动解析响应体来区分场景。
  • 通过"先尝试解析成功对象,失败后再解析错误对象"的方式,覆盖所有可能的响应情况。
  • 增加用户对象有效性校验,避免因服务器返回结构异常导致的误判。

内容的提问来源于stack exchange,提问作者esQmo_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:02:56