Flutter HTTP 请求封装

需求就是实现基础的 GET POST PUT DELETE 请求,能够自动对响应进行 Model 类封装,自动处理响应相关异常

下面代码仅实现了 GET 请求,且对于 401 等状态码还未做相应的处理

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:bubble_mobile/config.dart';
import 'package:bubble_mobile/main.dart';
import 'package:bubble_mobile/util/toast_utils.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

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

class Api {
  static const String _authHeader = "Authorization";
  static const String _authType = "Bearer";
  static String _token = "";

  static set token(String token) => _token = token;

  static Future<T?> doGet<T>(
      String uri, Map<String, dynamic> param, FromResp<T> fromResp,
      {int timeout = 1000}) async {
    debugPrint("Request GET $uri with param '${json.encode(param)}'");
    var url = _uri("$uri?${_param(param)}");
    Response resp;
    try {
      resp = await get(url, headers: _header())
          .timeout(Duration(milliseconds: timeout));
    } on TimeoutException {
      _onTimeout();
      return null;
    } catch (e) {
      _onException(e);
      return null;
    }
    return _resp(resp, fromResp);
  }

  static Map<String, String> _header() {
    return {
      if (_token.isNotEmpty) _authHeader: "$_authType $_token",
    };
  }

  static Uri _uri(String uri) {
    return Uri.parse(
            "$serverUrl/$uri".replaceAll(RegExp("(?<!(http:|https:))/+"), "/"))
        .normalizePath();
  }

  static String _param(Map<String, dynamic> param) {
    var paramStr = "";
    param.forEach((key, value) {
      paramStr += "$key=$value&";
    });
    if (paramStr.endsWith("&")) {
      paramStr = paramStr.substring(0, paramStr.length - 1);
    }
    return paramStr;
  }

  static void _onTimeout() {
    debugPrint("Request timeout");
    Toast.show(
        AppLocalizations.of(globalKey.currentState!.context)!.apiTimeout);
  }

  static void _onException(Object e) {
    debugPrint("Request failed with exception $e");
    Toast.show(
        AppLocalizations.of(globalKey.currentState!.context)!.apiTimeout);
  }

  static T? _resp<T>(Response resp, FromResp<T> fromResp) {
    if (resp.statusCode != HttpStatus.ok) {
      debugPrint("Request failed with response code ${resp.statusCode}");
      Toast.show(
          AppLocalizations.of(globalKey.currentState!.context)!.apiTimeout);
      return null;
    }
    return fromResp.call(json.decode(utf8.decode(resp.bodyBytes)));
  }
}

class Svr {
  static const String userSvr = "user-svr";
}

使用

var accountExists = await Api.doGet("${Svr.userSvr}/auth/account-exists",
        {"countryId": "1", "telNo": _telNo}, AccountExists.fromJson);
posted @ 2022-08-07 16:04  seliote  阅读(219)  评论(0)    收藏  举报