我需要创建一个拦截器,每当我的API响应是401时,我需要用refreshToken刷新令牌,如果出现错误,我需要将用户重定向到LoginPage。
但是在refreshToken方法内部传递BuildContext时遇到了一些困难...我使用的是http_interceptor依赖项。
class AuthedApiClient {
http.Client client = InterceptedClient.build(
interceptors: [AuthorizationInterceptor()],
requestTimeout: const Duration(seconds: 10),
);
static Future<void> refreshToken(BuildContext context) async {
LoginService loginService = LoginService();
try {
loginService.refreshLogin();
} catch (e) {
if (e is RefreshTokenException) {
Fluttertoast.showToast(
msg: e.message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
textColor: Colors.black,
backgroundColor: ThemeColors.errorToastMessage,
fontSize: 12.0,
);
}
Navigator.pushReplacementNamed(context, '/');
}
}
}
class AuthorizationInterceptor implements InterceptorContract {
Logger logger = Logger();
@override
Future<RequestData> interceptRequest({required RequestData data}) async {
logger.v(
"Requisição para: ${data.baseUrl}\nCabeçalhos: ${data.headers}\nCorpo: ${data.body}");
try {
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('token');
data.headers.clear();
data.headers['Authorization'] = 'Bearer ${token!}';
data.headers['Content-type'] = 'application/json';
data.headers['Client'] = 'CustomerApp';
} catch (e) {
logger.e(e);
}
return data;
}
@override
Future<ResponseData> interceptResponse({required ResponseData data}) async {
return data;
}
}
class ExpiredTokenRetryPolicy extends RetryPolicy {
@override
Future<bool> shouldAttemptRetryOnResponse(ResponseData response) async {
if (response.statusCode == 401) {
await AuthedApiClient
.refreshToken(); //I need to somehow pass the context to this guy here...
return true;
}
return false;
}
}
1条答案
按热度按时间xdnvmnnf1#
有时候,我们可能无法在我们的应用程序中获取当前的
context
,在这些情况下,我们应该考虑使用全局上下文.对于使用全局上下文,我们需要做的是:
创建一个
class
,如下所示:现在,在
MaterialApp
中,将navigatorKey指定为:现在,要在
refreshToken
函数中获取BuildContext,您不需要将context
定义为参数。将此
Navigator.pushReplacementNamed(context, '/');
替换为:你就完了。