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

遭遇ChangeNotifierProxyProvider已释放异常,401 API重试失败

解决ChangeNotifierProxyProvider已释放后仍被使用的API重试问题

问题根源分析

你遇到的核心问题是重试API时触发ChangeNotifierProxyProvider was used after being disposed异常,尽管能成功刷新AccessToken,但重试调用依然失败。问题出在ChangeNotifierProxyProvider的配置逻辑:当前update方法每次都新建ApiCalls实例,导致旧实例被销毁后,重试逻辑仍在引用它,进而引发释放后使用的错误。


解决方案

1. 修复ChangeNotifierProxyProvider的update逻辑

不要每次更新都新建ApiCalls实例,而是复用原有实例并更新token:

ChangeNotifierProxyProvider<Auth, ApiCalls>(
  create: (_) => ApiCalls(null),
  update: (context, auth, previous) {
    // 复用已有实例,仅更新token
    previous?.updateToken(auth.token);
    return previous!;
  },
)

同时在ApiCalls类中添加更新token的方法:

class ApiCalls extends ChangeNotifier {
  String? _token;

  ApiCalls(this._token);

  void updateToken(String? newToken) {
    _token = newToken;
    // 若需触发UI更新,可调用notifyListeners();
  }

  // 你的API调用方法,使用_token做授权校验
}

2. 确保重试时使用最新token

在onRetry回调中,等待token刷新完成后,重新构建请求并替换授权头:

final client = RetryClient(
  http.Client(),
  retries: 1,
  when: (response) => response.statusCode == 401,
  onRetry: (req, res, retryCount) async {
    print('retry started');
    if (retryCount == 0 && res?.statusCode == 401) {
      // 等待token刷新完成
      await Provider.of<Auth>(context, listen: false).restoreAccessToken();
      // 获取最新token
      final newToken = Provider.of<Auth>(context, listen: false).token;
      // 复制原请求并替换Authorization头
      return req.copyWith(
        headers: {
          ...req.headers,
          'Authorization': 'Bearer $newToken',
        },
      );
    }
    return req;
  },
);

3. 额外注意事项

  • 确保Auth类的restoreAccessToken方法是异步实现,保证token刷新完成后再执行重试。
  • 检查ApiCalls实例的生命周期,避免在重试过程中被意外销毁。

内容的提问来源于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.20 23:06:22