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);