一、为什么需要封装Dio
1、迁移代码
当组件库中的方法发生改变,需要迁移的时候,如果有多处地方用到,那么需要对使用到的每个文件都进行修改,非常的繁琐而且很容易出问题。
2、请求库切换
当不需要Dio库的时候,我们可以试随时方便切换到别的网络库。
3、统一配置
因为一个应用程序基本都是统一的配置方式,所以我们可以针对拦截器 、转换器 、 缓存 、统一处理错误 、代理配置、证书校验 等多个配置进行统一管理。
二、使用单利模式进行Dio封装
1、为什么使用单例模式?
每个页面都会在进行网络请求,如果每次都要初始化一个dio,那么会增加系统不必要的开销,而使用单例模式对象一旦创建每次都是访问同一个对象,不会再实例化对象。
2、创建单例类
import 'package:dio/dio.dart';
class HttpRequest {
static final BaseOptions options = BaseOptions(baseUrl: "");
static final Dio dio = Dio(options);
static Future<T> request<T>(String url,
{String method, Map<String, dynamic> params, Interceptor inter}) async {
// 1.请求的单独配置
Options options = Options(method: method);
options.headers = httpHeaders;
// // 2.添加第一个拦截器
// Interceptor dInter =
// InterceptorsWrapper(onRequest: (RequestOptions options) {
// // 1.在进行任何网络请求的时候, 可以添加一个loading显示
//
// // 2.很多页面的访问必须要求携带Token,那么就可以在这里判断是有Token
//
// // 3.对参数进行一些处理,比如序列化处理等
// print("拦截了请求");
// return options;
// }, onResponse: (Response response) {
// print("拦截了响应");
// return response;
// }, onError: (DioError error) {
// print("拦截了错误");
// return error;
// });
//
// List<Interceptor> inters = [dInter];
// if (inter != null) {
// inters.add(inter);
// }
//
// dio.interceptors.addAll(inters);
// 3.发送网络请求
try {
Response response =
await dio.request(url, data: params, options: options);
return response.data;
} on DioError catch (e) {
return Future.error(e);
}
}
}
const httpHeaders = {
'Content-Type': 'application/json',
'X-LC-Id': 'a4Cj1Hm5aMrdhob6xGw71B5A-gzGzoHsz',
'X-LC-Key': 'XQaL1tUQC0DCQxBA9fpoR21C',
};
3、方法调用
HttpRequest.request(url, method: 'GET').then((res) {
var list = new GHAddressModel.fromJson(res).results;
setState(() {
this._list = list;
});
});
/// 收货地址列表
class GHAddressList extends StatefulWidget {
@override
_GHAddressListState createState() => _GHAddressListState();
}
class _GHAddressListState extends State<GHAddressList> {
/// 地址列表
var _list = [];
GlobalKey _easyRefreshKey = new GlobalKey();
_getAddressList() async {
//addressDetails
//shopAddress
var url = "https://a4cj1hm5.api.lncld.net/1.1/classes/shopAddress";
var c = Uri.encodeComponent('-createdAt');
var d = Uri.encodeComponent('李');
url = url + '?' + "order=" + c;
HttpRequest.request(url, method: 'GET').then((res) {
var list = new GHAddressModel.fromJson(res).results;
setState(() {
this._list = list;
});
});
}
void initState() {
super.initState();
this._easyRefreshKey.currentState;
}
void deactivate() {
// 返回到当前页刷新
var bool = ModalRoute.of(context).isCurrent;
if (bool) {
this._getAddressList();
}
}
Widget ListItem(Results results) {
return InkWell(
onTap: () {},
child: Container(
margin: EdgeInsets.only(top: 5, bottom: 5),
width: ScreenAdaper.getScreenWidth(),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row (
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: Row(
children: <Widget>[
Container(
width:50,
child: Text(
results.name,
overflow: TextOverflow.ellipsis,
style:TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(
width: 10,
),
Container(
child: Text(
results.phone,
style: TextStyle(fontSize: 16,fontWeight: FontWeight.bold),
),
),
],
),
),
Container(
width: ScreenAdaper.getScreenWidth() - 20 - 20 - 30,
child: Text(
results.province +
results.city +
results.area +
results.detailsAddress,
style: TextStyle(fontSize: 14, color: Colors.black54),
),
),
],
)
],
),
GestureDetector(
onTap: () {
Navigator.pushNamed(context, '/GHAddressEdit', arguments: {
'name': "${results.name}",
'zone': "${results.zone}",
'detailsAddress': "${results.detailsAddress}",
'phoneNumber': results.phone,
'objectId': results.objectId,
});
},
child: Container(
child: Icon(
Icons.edit,
size: 30,
),
),
),
],
),
Divider(),
],
)
),
);
}
@override
Widget build(BuildContext context) {
ScreenAdaper.init(context);
return Scaffold(
appBar: AppBar(
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.pushNamed(context, '/GHAddressEdit');
},
child: Icon(Icons.add),
)
],
title: Text("地址管理"),
),
body: Container(
padding: EdgeInsets.all(20),
child: EasyRefresh(
firstRefresh: true,
key:_easyRefreshKey,
onRefresh: () async {
await this._getAddressList();
},
onLoad: () async {
await this._getAddressList();
},
child: ListView.builder(
itemBuilder: (context, index) {
return ListItem(this._list[index]);
},
itemCount: this._list.length,
),
)),
);
}
}
三、数据转模型
我们当然不能手写来实现,我们使用quickType来进行转化。
数据请求后,转模型
HttpRequest.request(url, method: 'GET').then((res) {
var list = new GHAddressModel.fromJson(res).results;
setState(() {
this._list = list;
});
});
GHAddressModel类型
class GHAddressModel {
List<Results> results;
GHAddressModel({this.results});
GHAddressModel.fromJson(Map<String, dynamic> json) {
if (json['results'] != null) {
results = new List<Results>();
json['results'].forEach((v) {
results.add(new Results.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.results != null) {
data['results'] = this.results.map((v) => v.toJson()).toList();
}
return data;
}
}
class Results {
String province;
String area;
String city;
String detailsAddress;
String remark;
String zone;
String phone;
String userId;
String objectId;
String updatedAt;
String createdAt;
String name;
String isDefault;
Where where;
Results(
{this.detailsAddress,
this.remark,
this.province,
this.area,
this.city,
this.zone,
this.phone,
this.userId,
this.objectId,
this.updatedAt,
this.createdAt,
this.name,
this.isDefault,
this.where});
Results.fromJson(Map<String, dynamic> json) {
detailsAddress = json['detailsAddress'];
if (detailsAddress == null) {
detailsAddress = "暂无地址";
}
remark = json['remark'];
zone = json['zone'];
if (zone == null) {
zone = "暂无地址";
}
phone = json['phone'];
if (phone == null) {
phone = "13800000000";
}
userId = json['userId'];
objectId = json['objectId'];
updatedAt = json['updatedAt'];
createdAt = json['createdAt'];
province = json['province'];
city = json['city'];
area = json['area'];
name = json['name'];
if (name == null) {
name = "没有设置";
}
isDefault = json['isDefault'];
where = json['where'] != null ? new Where.fromJson(json['where']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['detailsAddress'] = this.detailsAddress;
data['remark'] = this.remark;
data['zone'] = this.zone;
data['phone'] = this.phone;
data['userId'] = this.userId;
data['objectId'] = this.objectId;
data['updatedAt'] = this.updatedAt;
data['createdAt'] = this.createdAt;
data['name'] = this.name;
data['isDefault'] = this.isDefault;
data['province'] = this.province;
data['city'] = this.city;
data['area'] = this.area;
if (this.where != null) {
data['where'] = this.where.toJson();
}
return data;
}
}
class Where {
String token;
String userId;
Where({this.token, this.userId});
Where.fromJson(Map<String, dynamic> json) {
token = json['token'];
userId = json['userId'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['token'] = this.token;
data['userId'] = this.userId;
return data;
}
}