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_
相关产品推荐
相关产品推荐

