英文:
Hot to pass BuildContext inside the RetryPolicy Interceptor
问题
以下是您要翻译的代码部分:
I need to create an interceptor that whenever my API response is 401, I need to refresh the token with the refreshToken. And if something goes wrong, I need to redirect the user to the LoginPage.
But I'm having some difficulties on passing the BuildContext inside the refreshToken method... I'm using the http_interceptor dependency.
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;
}
}
希望这对您有所帮助!
英文:
I need to create an interceptor that whenever my API response is 401, I need to refresh the token with the refreshToken. And if something goes wrong, I need to redirect the user to the LoginPage.
But I'm having some difficulties on passing the BuildContext inside the refreshToken method... I'm using the http_interceptor dependency.
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
得分: 2
有时,我们可能无法在应用程序的任何地方获取当前的context
,在这种情况下,我们应该考虑使用全局上下文。
要使用全局上下文,我们需要执行以下操作:
创建一个类,如下所示:
class AppSettings {
static GlobalKey<NavigatorState> navigatorState = GlobalKey<NavigatorState>();
}
现在,在你的MaterialApp
中,将navigatorKey
设置为:
navigatorKey: AppSettings.navigatorState,
现在,在你的refreshToken
函数中获取BuildContext,你不需要将context
作为参数定义。
将这个:
Navigator.pushReplacementNamed(context, '/');
替换为:
Navigator.pushReplacementNamed(AppSettings.navigatorState.currentContext!, '/');
完成。
英文:
Sometimes we might not be able to get current context
in our app wherever we need, in those cases, We should consider using Global Context.
For using Global Context, What we need to do is:
create a class
like this:
class AppSettings {
static GlobalKey<NavigatorState> navigatorState = GlobalKey<NavigatorState>();
}
Now, inside your MaterialApp
give navigatorKey as:
navigatorKey: AppSettings.navigatorState,
Now, to get the BuildContext inside your refreshToken
function, you don't need to define context
as parameter.
Replace this Navigator.pushReplacementNamed(context, '/');
by:
Navigator.pushReplacementNamed(AppSettings.navigatorState.currentContext!, '/');
And you're done.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论