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
相关产品推荐
相关产品推荐

