在dart中使用可空参数调用泛型方法

b4lqfgs4  于 2023-06-19  发布在  其他
关注(0)|答案(1)|浏览(101)

我有以下方法:

enum RequestMethod {
  get,
  put,
  post,
  delete,
}

typedef FromJson<T> = T Function(Map<String, dynamic>);

class ApiHelper {
  Future<T?> apiRequest<T>(
    String endPoint,
    RequestMethod method, {
    FromJson<T>? create,
    Object body = '',
    bool secure = false,
  }) async {
    Response resp;
    final Map<String, String> headers = new Map<String, String>();
    headers.putIfAbsent(
      HttpHeaders.contentTypeHeader,
      () => 'application/json',
    );
    headers.putIfAbsent(
      HttpHeaders.acceptHeader,
      () => 'application/json',
    );
    if (secure) {
      final String? token = await SecureStorage().getToken();
      headers.putIfAbsent(
        HttpHeaders.authorizationHeader,
        () => 'Bearer $token',
      );
    }

    Uri url = Uri.https(
      apiUrl,
      endPoint,
    );

    try {
      if (method == RequestMethod.get) {
        resp = await http.get(
          url,
          headers: headers,
        );
      } else if (method == RequestMethod.put) {
        resp = await http.put(
          url,
          headers: headers,
          body: jsonEncode(body),
        );
      } else if (method == RequestMethod.post) {
        resp = await http.post(
          url,
          headers: headers,
          body: jsonEncode(body),
        );
      } else {
        resp = await http.delete(
          url,
          headers: headers,
        );
      }

      switch (resp.statusCode) {
        case 200:
          {
            // Get JSON object
            var data = json.decode(resp.body);

            // Parse the response form the API
            var api = ApiResponse<T>.fromJson(data, create);

            if (api.status.isSuccess) {
              /* Return the data from the API response */
              return api.data;
            }

            /* Something went wrong, return message to the user */
            throw ApiException(api.status.message);
          }
        case 400:
          throw BadRequestException(resp.body);
        case 401:
        case 403:
          throw UnauthorisedException(resp.body);
        case 500:
        case 404:
        default:
          throw FetchDataException(resp.statusCode);
      }
    } on TimeoutException {
      throw FetchDataException('Tiempo de espera agotado');
    } on SocketException {
      throw FetchDataException('Sin conexión');
    } on Error catch (e) {
      throw FetchDataException('Error general: $e');
    }
  }
}

class ApiResponse<T>{
  final T? data;
  final APIStatus status;

  ApiResponse({
    required this.status,
    required this.data,
  });

  factory ApiResponse.fromJson(
    Map<String, dynamic> json,
    FromJson<T>? create,
  ) =>
      new ApiResponse(
        status: APIStatus.fromJson(json["status"]),
        data: (json['data'] != null) ? create!(json['data']) : null,
      );
}

一些API方法返回一个对象,因此data != null,而其他方法返回data = null,例如:

@override
  Future signUp(
    String username,
    String password,
    String firstname,
    String lastname,
    String phone,
  ) async {
    return await api.apiRequest(
      "api/user/signUp",
      RequestMethod.get,
      body: {
        "email": username,
        "password": password,
        "firstname": firstname,
        "lastname": lastname,
        "phone": phone
      },
      secure: false,
    );
  }

该方法不期望任何返回。
在这两种情况下,我应该如何调用apiRequest来在下面的方法中强制使用一个非空的SignIn对象?

@override
  Future<SignIn> signIn(
    String username,
    String password,
  ) async {
    return await api.apiRequest<SignIn>(
      "api/user/signIn",
      RequestMethod.post,
      create: (json) => SignIn.fromJson(json),
      body: {
        "email": username,
        "password": password,
      },
      secure: false,
    )!;
  }

我得到了:

A value of type 'SignIn?' can't be returned from the method 'signIn' because it has a return type of 'Future<SignIn>'.

在这两种情况下,我应该如何调用apiRequest,以便没有可空的SignIn对象可以被强制执行?

e0bqpujr

e0bqpujr1#

你几乎得到了它,你只需要在await api.Request周围添加括号,因为否则它将强制未来为非空,而不是未来的结果。

return (await api.apiRequest<SignIn>(
      "api/user/signIn",
      RequestMethod.post,
      create: (json) => SignIn.fromJson(json),
      body: {
        "email": username,
        "password": password,
      },
      secure: false,
    ))!;

相关问题