diff --git a/client/lib/core/api/api_client.dart b/client/lib/core/api/api_client.dart index 154aaa0..cf666ee 100644 --- a/client/lib/core/api/api_client.dart +++ b/client/lib/core/api/api_client.dart @@ -14,25 +14,21 @@ final _publicDio = Dio(BaseOptions( )); final apiClientProvider = Provider((ref) { - final authState = ref.watch(authStateProvider); - final myToken = authState.user?.accessToken; + // 只监听登录/登出,不监听 token 内容变化。 + // token refresh 只改 accessToken,isLoggedIn 不变,provider 不重建, + // 避免旧 Dio 被 close 后还在执行 fetch 导致 "adapter was closed"。 + ref.watch(authStateProvider.select((s) => s.isLoggedIn)); + final user = ref.read(authStateProvider).user; final client = ApiClient( - token: myToken, - refreshToken: authState.user?.refreshToken, + token: user?.accessToken, + refreshToken: user?.refreshToken, onTokenRefreshed: (newToken) { - debugPrint('[ApiClient] token refreshed'); - if (ref.read(authStateProvider).user?.accessToken == myToken) { - ref.read(authStateProvider.notifier).updateAccessToken(newToken); - } + ref.read(authStateProvider.notifier).updateAccessToken(newToken); }, onAuthFailed: () { - debugPrint('[ApiClient] onAuthFailed! myToken prefix: ${(myToken ?? '').substring(0, (myToken ?? '').length.clamp(0, 20))}'); - if (ref.read(authStateProvider).user?.accessToken == myToken) { - debugPrint('[ApiClient] calling logout()'); + if (ref.read(authStateProvider).isLoggedIn) { ref.read(authStateProvider.notifier).logout(); - } else { - debugPrint('[ApiClient] skipping logout (stale client)'); } }, ); @@ -77,8 +73,10 @@ class ApiClient { }); final newToken = resp.data['data']['access_token'] as String; + // 原地更新 Dio 默认 headers,后续所有请求生效 + _dio.options.headers['Authorization'] = 'Bearer $newToken'; if (!_disposed) onTokenRefreshed?.call(newToken); - // 用新 token 重试原请求 + // 用新 token 重试原请求(此时 _dio 仍存活,不会 adapter closed) final opts = e.requestOptions; opts.headers['Authorization'] = 'Bearer $newToken'; final retryResp = await _dio.fetch(opts);