如何在Retrofit Interceptor中获取SharedPreferences中的Token?
你遇到的问题很典型——你的ServiceInterceptor是一个普通类,没有持有Android的Context对象,而访问SharedPreferences必须依赖Context,这就是你没法直接调用getSharedPreferences的原因。下面给你两种实用的解决方案:
方案一:通过构造函数传入Application Context
这是最直接的方式,我们给Interceptor添加一个接收Context的构造函数,注意一定要传入Application Context(避免持有Activity Context导致内存泄漏)。
修改后的Interceptor代码:
import android.content.Context import android.preference.PreferenceManager import okhttp3.Interceptor import okhttp3.Response class ServiceInterceptor(private val context: Context) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { var request = chain.request() // 跳过不需要认证的请求 if(request.header("No-Authentication") == null){ // 跳过登录请求,避免循环调用 if (!request.url.toString().contains("/user/signin")) { // 通过传入的Context获取SharedPreferences val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) // 安全获取token,处理null情况 val token = sharedPreferences.getString("token", "") ?: "" if (token.isNotEmpty()) { val finalToken = "Bearer $token" // 注入Authorization头 request = request.newBuilder() .addHeader("Authorization", finalToken) .build() } } } return chain.proceed(request) } }
在创建OkHttpClient时,传入Application Context:
// 在Application类或者Activity/Fragment中获取applicationContext val okHttpClient = OkHttpClient.Builder() .addInterceptor(ServiceInterceptor(applicationContext)) .build() // 然后构建Retrofit实例 val retrofit = Retrofit.Builder() .baseUrl("你的基础URL") .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build()
方案二:使用依赖注入(以Hilt为例)
如果你的项目已经用了Hilt这类依赖注入框架,可以直接注入Application Context,代码会更优雅,也不用手动管理Context的传递:
import android.content.Context import android.preference.PreferenceManager import dagger.hilt.android.qualifiers.ApplicationContext import okhttp3.Interceptor import okhttp3.Response import javax.inject.Inject class ServiceInterceptor @Inject constructor( @ApplicationContext private val context: Context ) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { var request = chain.request() if(request.header("No-Authentication") == null){ if (!request.url.toString().contains("/user/signin")) { val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) val token = sharedPreferences.getString("token", "") ?: "" if (token.isNotEmpty()) { val finalToken = "Bearer $token" request = request.newBuilder() .addHeader("Authorization", finalToken) .build() } } } return chain.proceed(request) } }
关键注意点
- 必须用Application Context:如果传入Activity/Fragment的Context,当组件销毁时,Interceptor还持有引用会引发内存泄漏。
- 处理null值:
getString("token")可能返回null,所以用?: ""来兜底,避免空指针异常。 - 修正SharedPreferences调用:你原来的
PreferenceManager.getSharedPreferences()是错误的,正确的默认SharedPreferences获取方法是getDefaultSharedPreferences(Context)。
内容的提问来源于stack exchange,提问作者wawanopoulos
相关产品推荐
相关产品推荐

