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

如何在Retrofit Interceptor中获取SharedPreferences中的Token?

解决Retrofit Interceptor中获取SharedPreferences的问题

你遇到的问题很典型——你的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:04:46