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

Retrofit无法更新请求Header中新Token问题求助

问题根源分析

哥们,你的问题出在Retrofit单例的初始化逻辑和Token的绑定方式上!核心原因是:第一次创建Retrofit实例时,拦截器就把当时传入的Token固定下来了。因为你的RetrofitClient是单例模式,只要retrofit不为null就直接返回旧实例,后续即使传入新Token,旧拦截器里捕获的还是最初的Token值,自然不会更新。

另外还有个容易忽略的小错误:你直接用new OkHttpClient()然后添加拦截器的方式是错的——OkHttpClient是不可变类,必须通过Builder构建才能让拦截器正确生效。

解决方案

1. 让拦截器动态读取最新Token

把拦截器里的Token从传入参数改成每次请求时从SharedPreferences实时获取,这样不管Token什么时候更新,请求都会用最新的值。

2. 修复OkHttpClient的构建方式

改用OkHttpClient.Builder来创建客户端,确保拦截器能被正确添加并生效。

3. 可选:添加重置Retrofit实例的方法

虽然动态读取Token已经能解决核心问题,但添加一个重置方法可以在Token更新时强制重建客户端,让逻辑更严谨。

修改后的代码

RetrofitClient 代码

public class RetrofitClient {
    private static Retrofit retrofit = null;

    // 去掉token参数,拦截器会动态从SharedPreferences获取
    public static Retrofit getClient() {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);

        // 用Builder构建OkHttpClient,这才是正确的姿势
        OkHttpClient okClient = new OkHttpClient.Builder()
                .addInterceptor(chain -> {
                    Request original = chain.request();
                    // 每次请求都实时获取最新Token
                    String token = AuthUser.getInstance().getToken(); // 替换成你获取Token的实际方式
                    Request request = original.newBuilder()
                            .header(Config.X_AUTH_TOKEN, "Bearer " + token)
                            .method(original.method(), original.body())
                            .build();
                    Log.d("Authorization", token);
                    return chain.proceed(request);
                })
                .addInterceptor(logging)
                .build();

        if (retrofit == null) {
            Gson gson = new GsonBuilder()
                    .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                    .create();
            
            retrofit = new Retrofit.Builder()
                    .baseUrl(Config.BASE_URL1)
                    .client(okClient)
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
        }
        return retrofit;
    }

    // 新增:Token更新时调用,清空旧的Retrofit实例(可选,动态读取Token生效后可省略)
    public static void resetClient() {
        retrofit = null;
    }
}

登录成功后的调用示例

// 保存新Token到SharedPreferences
authUser.setToken(newToken);
// 可选:重置Retrofit客户端,下次请求会重建实例
RetrofitClient.resetClient();
为什么这样能解决问题?
  • 拦截器不再依赖固定的传入Token,而是每次请求都从SharedPreferences读取最新值,确保Token实时生效。
  • 用OkHttpClient.Builder构建客户端,保证拦截器被正确添加并作用于所有请求。
  • 可选的resetClient()方法可以在Token变更后强制重建Retrofit实例,避免任何潜在的缓存问题。

内容的提问来源于stack exchange,提问作者Lending Square

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:44:37