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

Flutter ProxyProvider未更新值:API重试无法获取最新token

问题分析与解决方案

核心问题是RetryClient重试时未实时获取Auth实例更新后的token,同时ProxyProvider的依赖传递逻辑可能未同步触发ApiCalls的token更新,导致请求头仍使用旧值。以下是具体修复步骤:

1. 确保Auth类的token更新后立即通知监听者

在restoreAccessToken方法中,必须在token变量更新完成后调用notifyListeners(),确保所有依赖Auth的Provider能感知到状态变化:

class Auth extends ChangeNotifier {
  String? _accessToken;

  String? get accessToken => _accessToken;

  Future<void> restoreAccessToken() async {
    // 调用刷新token的API接口
    final response = await http.post(Uri.parse('your-refresh-token-url'));
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      _accessToken = data['access_token'];
      // 关键:更新后立刻通知监听者
      notifyListeners();
    }
  }
}

2. 修正ProxyProvider的更新逻辑

不要在ProxyProvider中缓存token值,而是让ApiCalls实时依赖Auth实例,或者提供token更新方法:

// main.dart中的MultiProvider配置
MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (context) => Auth()),
    ProxyProvider<Auth, ApiCalls>(
      update: (context, auth, apiCalls) {
        // 如果ApiCalls已存在,更新其token;否则创建新实例
        if (apiCalls != null) {
          apiCalls.updateToken(auth.accessToken);
          return apiCalls;
        }
        return ApiCalls(auth.accessToken);
      },
    ),
  ],
  child: const MyApp(),
)

// ApiCalls类新增updateToken方法
class ApiCalls {
  String? _token;

  ApiCalls(this._token);

  void updateToken(String? newToken) {
    _token = newToken;
  }

  Future<void> postVehicles() async {
    // 后续请求直接使用当前的_token
    final headers = {
      'Authorization': 'Bearer $_token',
      'Content-Type': 'application/json',
    };
    // 发起请求逻辑
  }
}

3. 调整RetryClient的重试逻辑,实时获取最新token

在onRetry回调中,直接从Provider获取Auth实例并刷新token,然后同步更新ApiCalls的token:

final retryClient = RetryClient(
  http.Client(),
  onRetry: (req, res, retryCount) async {
    if (res?.statusCode == 401) {
      // 获取Auth实例,listen: false避免UI监听
      final auth = Provider.of<Auth>(context, listen: false);
      await auth.restoreAccessToken();
      // 更新ApiCalls的token
      final apiCalls = Provider.of<ApiCalls>(context, listen: false);
      apiCalls.updateToken(auth.accessToken);
      // 更新当前请求的头信息
      req.headers['Authorization'] = 'Bearer ${auth.accessToken}';
    }
  },
);

4. 避免缓存token,每次请求动态获取

如果不想依赖ApiCalls的token缓存,也可以在每次请求时直接从Auth实例拿最新token:

Future<void> postVehicles(BuildContext context) async {
  final auth = Provider.of<Auth>(context, listen: false);
  final headers = {
    'Authorization': 'Bearer ${auth.accessToken}',
    'Content-Type': 'application/json',
  };
  // 使用retryClient发起请求
  final response = await retryClient.post(
    Uri.parse('your-api-url'),
    headers: headers,
    body: jsonEncode(/* 请求体 */),
  );
}

内容的提问来源于stack exchange,提问作者Santosh Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:20:36