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

使用Retrofit和SharedPreferences时登录Token请求报错排查与修复

常见NullPointerException原因及修正方案

一、SharedPreferences实例初始化问题

  • 错误场景:存储/读取Token时,SharedPreferences实例为null,比如在未初始化的Context环境下调用getSharedPreferences,或是在Application生命周期启动前尝试获取实例。
  • 修正:
    • 使用全局Application Context初始化SharedPreferences,避免依赖Activity Context引发的内存泄漏或实例空值问题:
      public class MyApp extends Application {
          private static SharedPreferences tokenSp;
      
          @Override
          public void onCreate() {
              super.onCreate();
              tokenSp = getSharedPreferences("token_storage", MODE_PRIVATE);
          }
      
          public static SharedPreferences getTokenSp() {
              return tokenSp;
          }
      }
      
    • 存储Token时调用全局实例:
      MyApp.getTokenSp().edit().putString("user_token", serverReturnedToken).apply();
      

二、Retrofit拦截器中Token处理空指针

  • 错误场景:拦截器中获取Token时,要么SharedPreferences未初始化,要么键名拼写错误导致返回null,后续拼接"Bearer " + token时触发NPE。
  • 修正:
    • 在拦截器中先判断Token是否存在,再添加请求头:
      public class TokenInterceptor implements Interceptor {
          @Override
          public Response intercept(Chain chain) throws IOException {
              Request original = chain.request();
              String token = MyApp.getTokenSp().getString("user_token", null);
              
              Request finalRequest;
              if (token != null && !token.isEmpty()) {
                  finalRequest = original.newBuilder()
                          .header("Authorization", "Bearer " + token)
                          .build();
              } else {
                  finalRequest = original;
              }
              return chain.proceed(finalRequest);
          }
      }
      
    • 确保Retrofit初始化时正确绑定拦截器,且拦截器依赖的SharedPreferences已完成初始化:
      Retrofit retrofit = new Retrofit.Builder()
              .baseUrl(BASE_API_URL)
              .addConverterFactory(GsonConverterFactory.create())
              .client(new OkHttpClient.Builder()
                      .addInterceptor(new TokenInterceptor())
                      .build())
              .build();
      

三、Token存储时机错误

  • 错误场景:登录成功后未及时存储Token,或是存储操作在异步线程中未完成就发起需要Token的请求,导致读取时Token为null。
  • 修正:
    • 在登录接口的成功回调中同步存储Token,确认存储完成后再发起后续请求:
      loginApi.login(loginRequestBody).enqueue(new Callback<LoginResp>() {
          @Override
          public void onResponse(Call<LoginResp> call, Response<LoginResp> response) {
              if (response.isSuccessful() && response.body() != null) {
                  LoginResp resp = response.body();
                  if (resp.getResultCode() == 200) {
                      // 立即存储Token
                      MyApp.getTokenSp().edit().putString("user_token", resp.getToken()).apply();
                      // 再执行需要Token的接口请求
                      loadUserInfo();
                  }
              }
          }
      
          @Override
          public void onFailure(Call<LoginResp> call, Throwable t) {
              // 处理请求失败逻辑
          }
      });
      

四、非空判断缺失

  • 错误场景:读取Token后未做非空校验就直接使用,比如直接执行header("Authorization", "Bearer " + token),当token为null时触发NPE。
  • 修正:
    • 所有使用Token的场景都先添加非空判断,确保变量有效后再执行后续逻辑。

内容的提问来源于stack exchange,提问作者박종준

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:31:14