flutter dio 封装(增加 loading dialog)
flutter dio 封装(log 打印)
flutter dio封装(返回值泛型的处理)
这边只列举 get 和 post 方法
1).GET方法
get(String url,
{HttpCallBack success,
HttpCallBack special,
HttpCallBack error,
bool hasLoading,
BuildContext context}) async {
_http(HttpMethod.GET, url, null,
success: success,
special: special,
error: error,
hasLoading: hasLoading,
context: context);
}
2).Post方法
post(String url, Map map,
{HttpCallBack success,
HttpCallBack special,
HttpCallBack error,
bool hasLoading,
BuildContext context}) async {
_http(HttpMethod.POST, url, map,
success: success,
special: special,
error: error,
hasLoading: hasLoading,
context: context);
}
这边使用泛型来代替参数:
T 表示返回的是否是集合,有HttpResponseEntity和HttpResponseListEntity两种
G 表示返回的是接口返回的类型(即你需要的类型)
这两个点后面会代码展示,先看_http 方法
_http(HttpMethod method, String url, Map map,
{HttpCallBack success,
HttpCallBack special,
HttpCallBack error,
bool hasLoading,
BuildContext context}) async {
this.context = context;
var header = await getHeader();
_options = BaseOptions(
connectTimeout: HttpConfig.connectTimeout,
receiveTimeout: HttpConfig.receiveTimeout,
baseUrl: HttpConfig.baseUrl,
headers: {
SharedPreConfig.TOKEN: header[SharedPreConfig.TOKEN],
SharedPreConfig.LOCATION: header[SharedPreConfig.LOCATION],
SharedPreConfig.UUID: header[SharedPreConfig.UUID],
SharedPreConfig.USER_AGENT: header[SharedPreConfig.USER_AGENT],
SharedPreConfig.NET_STATE: header[SharedPreConfig.NET_STATE]
});
_dio = Dio(_options);
_dio.interceptors
.add(InterceptorsWrapper(onRequest: (RequestOptions options) {
print(
"\n================================= 请求数据 =================================");
print("method = ${options.method.toString()}");
print("url = ${options.uri.toString()}");
print("headers = ${options.headers}");
print("params = ${options.queryParameters}");
}, onResponse: (Response response) {
print(
"\n================================= 响应数据开始 =================================");
print("code = ${response.statusCode}");
print("data = ${response.data}");
print(
"================================= 响应数据结束 =================================\n");
}, onError: (DioError e) {
print(
"\n=================================错误响应数据 =================================");
print("type = ${e.type}");
print("message = ${e.message}");
print("stackTrace = ${e.stackTrace}");
print("\n");
}));
if (hasLoading != null && context != null) {
this.hasLoading = hasLoading;
} else {
this.hasLoading = false;
}
showLoadingDialog();
try {
Response response = await _getResponse(method, url, map);
hiddeLoadingDialog();
if (response.statusCode == 200) {
if (response.data['Flag'] == 100) {
_httpSuccess(response.data, success);
} else {
_httpSpecial(response.data, special);
}
} else {
_httpError("网络状况不佳", error);
}
} catch (e) {
_httpError(e.toString(), error);
}
}
要显示 dialog 必须传入 context,并且 hasLoading 为 ture
主要的看下getResponse(),和回调方法
getResponse()方法:
_getResponse(HttpMethod method, String url, Map map) async {
Response response;
switch (method) {
case HttpMethod.GET:
response = await _dio.get(url);
return response;
case HttpMethod.POST:
response = await _dio.post(url, queryParameters: map);
return response;
case HttpMethod.PATCH:
response = await _dio.patch(url, queryParameters: map);
return response;
case HttpMethod.DELETE:
response = await _dio.delete(url, queryParameters: map);
return response;
case HttpMethod.PUT:
response = await _dio.put(url, queryParameters: map);
return response;
default:
response = await _dio.get(url);
return response;
}
}
通过getResponse 方法获得了 Response,然后对 response 进行处理
定义回调方法
typedef HttpCallBack = dynamic Function(P response);
response.statusCode==200为 ture 则请求接口成功
例如我这的接口返回格式是{"Flag": 100,"FlagString": "\u8bf7\u6c42\u6210\u529f","data": []}
_httpSuccess():处理成功回调
///statusCode==200&&Flag==100
_httpSuccess(Map response, HttpCallBack success) {
if (success != null) {
if (T.toString() == "HttpResponseEntity") {
success((HttpResponseEntity.fromJson(response).data));
} else if (T.toString() == "HttpResponseListEntity") {
success(HttpResponseListEntity.fromJson(response).data);
} else {
success(response['FlagString']);
}
}
}
可以看出,当 T 为HttpResponseEntity时,会返回 G,当 T为 HttpResponseListEntity 时,会返回 List
代码示例:
void _getHomeList(int currentPage) async {
await HttpUtil.getInstance().get(
'${HttpUrl.HOME_PAGE_URL}name=circle&page=${_currentPage}&sort=0',
success: (response) {
setState(() {
_homeList.addAll(response);
});
});
}
后续:
代码只是初步封装,后续会进一步完善。
贴下主要代码
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:percentage_flutter/config/SharedPreConfig.dart';
import 'package:percentage_flutter/widget/dialog/loading_dialog.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'http_config.dart';
import 'http_flag_code.dart';
import 'dart:convert';
import 'http_response_entity.dart';
typedef HttpCallBack = dynamic Function(P response);
enum HttpMethod { GET, POST, DELETE, PUT, PATCH }
///http 工具类
class HttpUtil {
HttpMethod method;
BaseOptions _options;
Dio _dio;
bool hasLoading;
BuildContext context;
static HttpUtil _instance;
static HttpUtil getInstance() {
if (_instance == null) {
_instance = HttpUtil();
}
return _instance;
}
///获取头部信息
dynamic getHeader() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String headerData = prefs.get(SharedPreConfig.NET_HEADER_DATA);
return json.decode(headerData);
}
get(String url,
{HttpCallBack success,
HttpCallBack special,
HttpCallBack error,
bool hasLoading,
BuildContext context}) async {
_http(HttpMethod.GET, url, null,
success: success,
special: special,
error: error,
hasLoading: hasLoading,
context: context);
}
post(String url, Map map,
{HttpCallBack success,
HttpCallBack special,
HttpCallBack error,
bool hasLoading,
BuildContext context}) async {
_http(HttpMethod.POST, url, map,
success: success,
special: special,
error: error,
hasLoading: hasLoading,
context: context);
}
delete(String url, Map map,
{HttpCallBack success,
HttpCallBack special,
HttpCallBack error,
bool hasLoading,
BuildContext context}) async {
_http(HttpMethod.DELETE, url, map,
success: success,
special: special,
error: error,
hasLoading: hasLoading,
context: context);
}
put(String url, Map map,
{HttpCallBack success,
HttpCallBack special,
HttpCallBack error,
bool hasLoading,
BuildContext context}) async {
_http(HttpMethod.PUT, url, map,
success: success,
special: special,
error: error,
hasLoading: hasLoading,
context: context);
}
patch(String url, Map map,
{HttpCallBack success,
HttpCallBack special,
HttpCallBack error,
bool hasLoading,
BuildContext context}) async {
_http(HttpMethod.PATCH, url, map,
success: success,
special: special,
error: error,
hasLoading: hasLoading,
context: context);
}
_http(HttpMethod method, String url, Map map,
{HttpCallBack success,
HttpCallBack special,
HttpCallBack error,
bool hasLoading,
BuildContext context}) async {
this.context = context;
var header = await getHeader();
_options = BaseOptions(
connectTimeout: HttpConfig.connectTimeout,
receiveTimeout: HttpConfig.receiveTimeout,
baseUrl: HttpConfig.baseUrl,
headers: {
SharedPreConfig.TOKEN: header[SharedPreConfig.TOKEN],
SharedPreConfig.LOCATION: header[SharedPreConfig.LOCATION],
SharedPreConfig.UUID: header[SharedPreConfig.UUID],
SharedPreConfig.USER_AGENT: header[SharedPreConfig.USER_AGENT],
SharedPreConfig.NET_STATE: header[SharedPreConfig.NET_STATE]
});
_dio = Dio(_options);
_dio.interceptors
.add(InterceptorsWrapper(onRequest: (RequestOptions options) {
print(
"\n================================= 请求数据 =================================");
print("method = ${options.method.toString()}");
print("url = ${options.uri.toString()}");
print("headers = ${options.headers}");
print("params = ${options.queryParameters}");
}, onResponse: (Response response) {
print(
"\n================================= 响应数据开始 =================================");
print("code = ${response.statusCode}");
print("data = ${response.data}");
print(
"================================= 响应数据结束 =================================\n");
}, onError: (DioError e) {
print(
"\n=================================错误响应数据 =================================");
print("type = ${e.type}");
print("message = ${e.message}");
print("stackTrace = ${e.stackTrace}");
print("\n");
}));
if (hasLoading != null && context != null) {
this.hasLoading = hasLoading;
} else {
this.hasLoading = false;
}
showLoadingDialog();
try {
Response response = await _getResponse(method, url, map);
hiddeLoadingDialog();
if (response.statusCode == 200) {
if (response.data['Flag'] == 100) {
_httpSuccess(response.data, success);
} else {
_httpSpecial(response.data, special);
}
} else {
_httpError("网络状况不佳", error);
}
} catch (e) {
_httpError(e.toString(), error);
}
}
_getResponse(HttpMethod method, String url, Map map) async {
Response response;
switch (method) {
case HttpMethod.GET:
response = await _dio.get(url);
return response;
case HttpMethod.POST:
response = await _dio.post(url, queryParameters: map);
return response;
case HttpMethod.PATCH:
response = await _dio.patch(url, queryParameters: map);
return response;
case HttpMethod.DELETE:
response = await _dio.delete(url, queryParameters: map);
return response;
case HttpMethod.PUT:
response = await _dio.put(url, queryParameters: map);
return response;
default:
response = await _dio.get(url);
return response;
}
}
///statusCode==200&&Flag==100
_httpSuccess(Map response, HttpCallBack success) {
if (success != null) {
if (T.toString() == "HttpResponseEntity") {
success((HttpResponseEntity.fromJson(response).data));
} else if (T.toString() == "HttpResponseListEntity") {
success(HttpResponseListEntity.fromJson(response).data);
} else {
success(response['FlagString']);
}
}
}
///statusCode==200&&Flag!=100
_httpSpecial(Map response, HttpCallBack special) {
///可以针对不同的Flag 进行处理同一处理
if (special != null) {
special(response);
} else {
switch (response['Flag']) {
case HttpFlagCode.FLAG_7:
break;
default:
Fluttertoast.showToast(
msg: response['FlagString'],
fontSize: 14,
toastLength: Toast.LENGTH_SHORT,
);
}
}
}
///statusCode!=200
_httpError(String errorMsg, HttpCallBack error) {
print('httpError-----$errorMsg');
if (error != null) {
error(ErrorResponse('999', '网络状况不佳').toJson());
}
}
showLoadingDialog() {
if (hasLoading) {
showDialog(
context: context, //BuildContext对象
barrierDismissible: false,
builder: (BuildContext context) {
return LoadingDialog();
});
}
}
hiddeLoadingDialog() {
if (hasLoading) {
Navigator.pop(context);
}
}
}
class ErrorResponse {
String Flag;
String FlagString;
ErrorResponse(this.Flag, this.FlagString);
Map toJson() {
final Map data = new Map();
data['Flag'] = this.Flag;
data['FlagString'] = this.FlagString;
return data;
}
}