dio是Flutter中文网开源的一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等...
最近想用flutter写个商城项目,下载一些demo后发现dio都不封装下就使用,像使用flutter的大多数都是Android开发转过来的,习惯性封装okhttp,将 Response 里返回的数据在工具类里处理好再返回业务层处理,从而大大减少代码量,使之更加清晰简洁,接下来代码走起...
目录
一、示例使用
一个登陆操作的post请求
var APILongin="http://192.168.1.144:8085/sso/login";
_LoginPost() {
///入参
Map<String, dynamic> map = Map();
map.putIfAbsent("username", () => "10086");
map.putIfAbsent("password", () => "132456";
DioUtils.instance.postHttp<TokenBeanEntity>(url: APILongin,parameters: map,onSuccess:
(datas){
print(datas);
}, onError: (error){
print("error");
});
}
}
_LoginPost() {
///入参
Map<String, dynamic> map = Map();
map.putIfAbsent("username", () => "10086");
map.putIfAbsent("password", () => "132456";
DioUtils.instance.postHttp<TokenBeanEntity>(url: APILongin,parameters: map,onSuccess:
(datas){
print(datas);
}, onError: (error){
print("error");
});
}
}
// patch put delect get post 都可以使用,添加 method 即可
_LoginPut() {
///入参
Map<String, dynamic> map = Map();
map.putIfAbsent("username", () => "10086");
map.putIfAbsent("password", () => "132456";
DioUtils.instance.getHttp<TokenBeanEntity>(url: APILongin,method : DioUtils.GET ,parameters: map,onSuccess:
(datas){
print(datas);
}, onError: (error){
print("error");
});
}
}
不需要返回参数
第一种方式
/// 无参数返回 get
get DioUtils.instance.getHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" );
/// 无参数返回 post
get DioUtils.instance.postHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" );
第二种方式
/// 无参数返回 get
DioUtils.instance.postHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" ,
method : DioUtils.GET );
/// 无参数返回 post
DioUtils.instance.postHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" ,
method : DioUtils.POST);
/// 无参数返回 delete
DioUtils.instance.postHttp<UserBeanEntity>(url:"http://192.168.1.144:8085/sso/info" ,
method : DioUtils.DELETE);
二、依赖库
打开pubspec.yaml ,添加dio依赖即可,然后pubget
dependencies:
flutter:
sdk: flutter
dio: ^3.0.9 /// 添加flutter中文网最新的即可
三、创建一个Dio实例以及Dio封装
创建DioUtils.dart工具类
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:mall/api/api.dart';
import 'package:mall/http/BaseBean.dart';
import 'package:mall/http/LogInterceptors.dart';
class DioUtils {
static var dio;
static var httpUtil;
static DioUtils get instance => _getInstance();
static DioUtils _getInstance() {
if (httpUtil == null) {
httpUtil = DioUtils();
}
return httpUtil;
}
static const String API_PREFIX = 'https://novel.dkvirus.com/api/v1';
static const int CONNECT_TIMEOUT = 10000;
static const int RECEIVE_TIMEOUT = 10000;
static const String GET = 'get';
static const String POST = 'post';
static const String PUT = 'put';
static const String PATCH = 'patch';
static const String DELETE = 'delete';
///Get请求
void getHttp <T>( { String url, parameters, Function(T t) onSuccess, Function(String error) onError, }) async {
try {
Dio dio = createInstance();
Response response = await dio.get(Api.BASE_URL);
response= await dio.get((url==null||url.isEmpty)?Api.BASE_URL : url,queryParameters: parameters);
getResponse(url: url,method :GET ,parameters: parameters,onSuccess: onSuccess,onError: onError);
} catch (e) {
print(e);
}
}
///Post请求 && put delect...
void postHttp<T>(
{ String url,
String method,
parameters,
Function(T t) onSuccess,
Function(String error) onError,
}) async {
///定义请求参数
parameters = parameters ?? {};
getResponse(url: url,parameters: parameters,onSuccess: onSuccess,onError: onError);
}
void getResponse<T>({ String url, String method, parameters, Function(T t) onSuccess, Function(String error) onError, }) async {
try {
Response response;
Dio dio = createInstance();
switch(method){
case GET:
response= await dio.get((url==null||url.isEmpty)?Api.BASE_URL : url, queryParameters: parameters);
break;
case PUT:
response= await dio.put((url==null||url.isEmpty)?Api.BASE_URL : url, queryParameters: parameters);
break;
case PATCH:
response= await dio.patch((url==null||url.isEmpty)?Api.BASE_URL : url, queryParameters: parameters);
break;
case DELETE:
response= await dio.delete((url==null||url.isEmpty)?Api.BASE_URL : url, queryParameters: parameters);
break;
default:
response= await dio.post((url==null||url.isEmpty)?Api.BASE_URL : url, data: parameters);
break;
}
/// 拦截http层异常码
if (response.statusCode == 200) {
/// 这里做baseBena泛型解析,封装 并拦截后台code异常码,可拦截自定义处理
BaseBean<T>bean=BaseBean.fromJson(response.data);
if(bean.code==200&&onSuccess != null){
/// 返回泛型Bean
onSuccess( bean.data);
}else{
onError(bean.message);
}
} else {
throw Exception('statusCode:${response.statusCode}+${response.statusMessage}');
}
} catch (e) {
print('请求出错:' + e.toString());
onError(e.toString());
}
}
/// @ url 请求链接
///@ parameters 请求参数
///@ metthod 请求方式
///@ onSuccess 成功回调
///@ onError 失败回调
Future<Map> request<T>(String url,
{parameters,
method,
Function(T t) onSuccess,
Function(String error) onError}) async {
parameters = parameters ?? {};
method = method ?? 'GET';
/// 请求处理
parameters.forEach((key, value) {
if (url.indexOf(key) != -1) {
url = url.replaceAll(':$key', value.toString());
}
});
Dio dio = createInstance();
//请求结果
var result;
try {
Response response = await dio.request(url,
data: parameters, options: new Options(method: method));
result = response.data;
if (response.statusCode == 200) {
if (onSuccess != null) {
var data = json.decode(response.data) ;
onSuccess(data);
}
} else {
throw Exception('statusCode:${response.statusCode}');
}
} on DioError catch (e) {
print('请求出错:' + e.toString());
onError(e.toString());
}
return result;
}
/// 初始化DIO
Dio createInstance() {
if (dio == null) {
/// 全局属性:请求前缀、连接超时时间、响应超时时间
var options = BaseOptions(
connectTimeout: 15000,
receiveTimeout: 15000,
//responseType: ResponseType.plain,
validateStatus: (status) {
// 不使用http状态码判断状态,使用AdapterInterceptor来处理(适用于标准REST风格)
return true;
},
// baseUrl: "http://poetry.huhustory.com/",
);
dio = new Dio(options);
/// 增加拦截器并添加heands头 token
dio.interceptors.add(LogInterceptors(dio));
}
return dio;
}
/// 清空 dio 对象
clear() {
dio = null;
}
}
四、Dio拦截器
import 'package:dio/dio.dart';
import 'package:mall/utils/shared_preferences_util.dart';
///日志拦截器
class LogInterceptors extends InterceptorsWrapper {
Dio dio;
LogInterceptors(this.dio);
@override
Future onRequest(RequestOptions options) async {
print("========================请求数据===================");
print("【请求baseUrl】${options.uri}");
// print("【请求path】${options.path}");
// print("【请求headers】${options.headers.toString()}");
print("【请求参数】${options.data.toString()}");
dio.lock();
await SharedPreferencesUtils.getToken().then((token) {
if(token==null||token.toString().isEmpty){
return;
}
Map<String,String> parms = {"Authorization" : "Bearer "+token};
options.headers.addAll(parms);
});
dio.unlock();
return options;
return super.onRequest(options);
}
@override
Future onResponse(Response response) {
print("【返回statusCode】${response.statusCode}");
// print("【返回headers】${response.headers.toString()}");
// print("【返回extra】${response.extra.toString()}");
print("【返回data】${response.data.toString()}");
return super.onResponse(response);
}
@override
Future onError(DioError err) {
print("========================请求错误===================");
formatError(err);
return super.onError(err);
}
/// error统一处理
void formatError(DioError e) {
if (e.type == DioErrorType.CONNECT_TIMEOUT) {
print(e.hashCode.toString() + "连接超时");
} else if (e.type == DioErrorType.SEND_TIMEOUT) {
print(e.hashCode.toString() + "请求超时");
} else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
print(e.hashCode.toString() + "响应超时");
} else if (e.type == DioErrorType.RESPONSE) {
print(e.hashCode.toString() + "出现异常404 503");
} else if (e.type == DioErrorType.CANCEL) {
print(e.hashCode.toString() + "请求取消");
} else {
print("message =${e.message}");
}
}
}
五、JSON解析
这里BaseBean<UserBeanEntity>泛型解析 使用插件FlutterJsonBeanFactory生成dart class实体类,androidStudio用户可以下载FlutterJsonBeanFactory插件,然后重启AS
泛型解析这边是刚好看到一锅子鱼这位兄弟的的博客改写的,大家可以去看下
创建 BaseBean<T> ,安装好FlutterJsonBeanFactory的时候new JsonToDartBeanAction,会自动生成json_convert_content.dart文件在项目中,并且会在JsonConvert里生成fromJsonAsT方法
import 'package:mall/generated/json/base/json_convert_content.dart';
///convert和FlutterJsonBeanFactory结合解析
class BaseBean<T> {
T data;
int code;
String message;
BaseBean({this.data, this.code, this.message});
BaseBean.fromJson(Map<String, dynamic> json) {
if (json['data'] != null&&json['data']!='null') {
data = JsonConvert.fromJsonAsT<T>(json['data']);
}
code = json['code'];
message = json['message'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data;
}
data['code'] = this.code;
data['message'] = this.message;
return data;
}
}
import 'package:mall/generated/json/base/json_convert_content.dart';
class TokenBeanEntity with JsonConvert<TokenBeanEntity> {
String tokenHead;
String token;
}
完结...