如何将SharedPreferences存储的token添加到OkHttp拦截器中
解决方案
步骤1:创建全局Application类提供ApplicationContext
因为SharedPreferences需要Context才能访问,使用Application级别的全局Context不会造成内存泄漏,是最稳妥的方案:
- 新建自定义Application类:
public class MyApp extends Application { private static Context appContext; @Override public void onCreate() { super.onCreate(); appContext = getApplicationContext(); } // 对外提供全局Context public static Context getAppContext() { return appContext; } }
- 在
AndroidManifest.xml的<application>标签中注册这个自定义Application:
<application android:name=".MyApp" <!-- 其余原有配置不变 --> > <!-- 四大组件配置 --> </application>
步骤2:修改ApiClient拦截器逻辑,动态读取token
直接在拦截器中通过全局Context读取SharedPreferences中存储的token即可:
public class ApiClient { private static Retrofit getRetrofit() { HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(httpLoggingInterceptor) .addInterceptor(chain -> { Request.Builder requestBuilder = chain.request().newBuilder(); // 读取SharedPreferences中的token SharedPreferences preferences = MyApp.getAppContext().getSharedPreferences("logged", Context.MODE_PRIVATE); String token = preferences.getString("token", ""); // 仅当token不为空时添加请求头,避免未登录请求携带无效头 if (!token.isEmpty()) { requestBuilder.addHeader("Authorization", token); } return chain.proceed(requestBuilder.build()); }) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://192.168.1.60:8080/") .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); return retrofit; } public static UserService getUserService() { return getRetrofit().create(UserService.class); } }
可选优化:Retrofit单例化
你现有代码每次调用getUserService都会重新创建Retrofit、OkHttpClient实例,会造成不必要的性能损耗,建议改成单例模式:
public class ApiClient { // 缓存Retrofit单例 private static Retrofit retrofitInstance; private static Retrofit getRetrofit() { if (retrofitInstance == null) { HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(httpLoggingInterceptor) .addInterceptor(chain -> { Request.Builder requestBuilder = chain.request().newBuilder(); SharedPreferences preferences = MyApp.getAppContext().getSharedPreferences("logged", Context.MODE_PRIVATE); String token = preferences.getString("token", ""); if (!token.isEmpty()) { requestBuilder.addHeader("Authorization", token); } return chain.proceed(requestBuilder.build()); }) .build(); retrofitInstance = new Retrofit.Builder() .baseUrl("http://192.168.1.60:8080/") .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); } return retrofitInstance; } public static UserService getUserService() { return getRetrofit().create(UserService.class); } }
后续你登出账号清空SharedPreferences中的token后,拦截器会自动停止携带Authorization头,无需额外处理。
内容的提问来源于stack exchange,提问作者Pollongz
相关产品推荐
相关产品推荐

