如何在我的API请求类(无widget类)中访问bloc?

3
我正在使用flutter_bloc(https://felangel.github.io/bloc/#/gettingstarted)包,这个包非常棒。目前,我有一个认证bloc,在用户登录时保存访问令牌。
在我的许多HTTP请求中,我需要将访问令牌发送到后端。
我正在创建一个可重用的函数,以处理所有需要发送访问令牌的受保护HTTP请求。这样可以重复使用,因此我不必从UI层传递访问令牌到API层。然而,我不确定如何从这个函数中访问Auth Bloc,因为它不在widget tree中。
当我进行HTTP请求时,数据流如下(基于felangel的flutter bloc教程):
UI -> bloc -> repository -> api 
and then:
api -> repository -> bloc -> UI

我在应用程序顶部附近有一个BlocProvider来提供AuthBloc,代码如下:

return BlocProvider(
    builder: (BuildContext context) =>
       AuthBloc(authRepository: authRepository),
       child: Scaffold( 
...

这是我用于受保护请求的可重复使用函数。我需要在此函数中访问Auth Bloc,但我不完全确定如何操作。

  Future<dynamic> protectedRequest(
      {accessToken, endpoint, dynamic body}) async {
    final uri = Uri.https(baseUrl, endpoint);
    final response = await http.post(uri,
        body: body, headers: {'Authorization': 'Bearer ' + accessToken});
    if (response.statusCode == 200 || response.statusCode == 201) {
      return response;
    } else {
      throw Exception();
    }
  }

谢谢你

1个回答

2

我可以为您提供一个dio包(https://pub.dev/packages/dio),它可以帮助您进行HTTP请求。使用该包,您可以创建一个HTTP管理器。

class HttpManager {
  static String token;
  static String cookie;
  final String tag;

  var _dio = Dio();
  HttpManager({this.tag}) {
    _dio.options..baseUrl = AppConfig.baseUrl;
    _dio.interceptors
        .add(InterceptorsWrapper(onRequest: (RequestOptions options) {
      if (token != null) {
        options.headers["Authorization"] = "Bearer $token";
        options.headers["cookie"] = cookie;
      }
      DioLogger.onSend(tag, options);
      return options;
    }, onResponse: (Response response) {
      DioLogger.onSuccess(tag, response);
      return response;
    }, onError: (DioError error) {
      if (error.response.statusCode == 401) {
        AuthenticationBloc().logout();
      } else if (error.response.statusCode == 400) {
        error.response.statusMessage = "400";
      }
      DioLogger.onError(tag, error);
      return error;
    }));
  }

  Dio get client => _dio;
}

您可以在身份验证服务中使用_dio变量,例如:
class AuthService {
  final String tag = "AuthService";
  Dio client;

  AuthService() {
    client = HttpManager(tag: tag).client;
  }

  Future<ResponseModel> authenticate(String username, String password) async {
    try {
       final response = await client.get("/myPath",
          queryParameters: {"username": username, "password": password});


      throwIfNoSuccess(response);

      HttpManager.token = response.data["token"];
      HttpManager.cookie = response.headers.value("cookie");

      return ResponseModel.fromJson(response.data);
    } catch (e) {
      throw (e);
    }
  }

  void throwIfNoSuccess(Response response) {
    print("is the response Null  : ${response.statusCode}");
    if ((response.statusCode ?? 0) < 200 || (response.statusCode ?? 0) > 299) {
      throw new HttpException(response);
    }
  }
}

谢谢,最终我选择了Dio,它运行得非常好! - wei
1
在HttpManager中使用AuthenticationBloc是一个好的解决方案吗?在这种情况下,它是单例的吗?在其他情况下,你是如何注入它的? - Anton
是的,authenticationBloc 是单例模式。在我的情况下,当遇到 401 错误时,我应该退出登录。所以我将其添加到了 HttpManager 中,想知道您的看法。 - Can Karabag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接