flutter 在RetryPolicy侦听器内部传递BuildContext的热

cidc1ykv  于 2023-02-25  发布在  Flutter
关注(0)|答案(1)|浏览(87)

我需要创建一个拦截器,每当我的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;
  }
}
xdnvmnnf

xdnvmnnf1#

有时候,我们可能无法在我们的应用程序中获取当前的context,在这些情况下,我们应该考虑使用全局上下文.
对于使用全局上下文,我们需要做的是:
创建一个class,如下所示:

class AppSettings {
  static GlobalKey<NavigatorState> navigatorState = GlobalKey<NavigatorState>();
}

现在,在MaterialApp中,将navigatorKey指定为:

navigatorKey: AppSettings.navigatorState,

现在,要在refreshToken函数中获取BuildContext,您不需要将context定义为参数。
将此Navigator.pushReplacementNamed(context, '/');替换为:

Navigator.pushReplacementNamed(AppSettings.navigatorState.currentContext!, '/');

你就完了。

相关问题