Flutter网络请求之简单封装

数据来源

接口数据来自张鸿洋大神的个人网站 www.wanandroid.com 的开放api,返回数据类型如下:

1
2
3
4
5
{
"data": ...,
"errorCode": 0,
"errorMsg": ""
}

errorCode>=0时为网络请求成功,data则为返回的数据;

errorCode<0时为网络请求失败,errorMsg则为返回的错误信息;

普通网络请求

先导包

1
2
import 'package:http/http.dart' as http;
import 'dart:convert';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
getBanners() async{
String url = "http://www.wanandroid.com/banner/json";

String errorMsg;
int errorCode;
var data;
try {
http.Response res = await http.get(url);
if(res.statusCode!=200){
errorMsg = "请求错误,错误码"+res.statusCode.toString();
print(errorMsg);
return;
}
Map<String, dynamic> map = json.decode(res.body);
errorCode = map['errorCode'];
errorMsg = map['errorMsg'];
data = map['data'];
// 这里实际上data是个list, List banners = data;
// >=0才请求成功
if(errorCode<0){
print(errorMsg);
return;
}
//这里偷懒直接打印数据
print("data:" + data.toString());
}catch(exception){
print(exception.toString());
}
}

请求结果(print可能打印的字符有上限)

返回结果

整个写下来的话,比较繁琐,需要先判断res.statusCode,以及数据的errorCode.然后再返回数据中的data部分.

那么接下来就稍微进行一下封装,直接返回了请求成功的数据(data部分)/错误信息(errorMsg或者请求过程中的其他错误信息)

目前对以下需求进行了封装

  • 一般的get请求
  • 一般的post请求

GET请求

1
2
3
4
5
6
7
8
9
//String url
//Function callback 成功回调,参数为var data
//Map<String, String> params 请求\参数
//Map<String, String> headers 请求头
//Function errorCallback 错误回调,参数为String errorMsg
get(String url, Function callback,
{Map<String, String> params,
Map<String, String> headers,
Function errorCallback}) async {}

普通使用

1
2
3
4
HttpUtil.get("banner/json", (data) {
List banners = data;
print(banners.toString());
});

带头带错误处理

1
2
3
4
5
6
7
8
Map<String, String> headers = new Map();
headers['Cookie'] = "我是cookie";
HttpUtil.get("banner/json", (data) {
List banners = data;
print(banners.toString());
}, errorCallback: (msg) {
print(msg);
}, headers: headers);

POST请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  _login() {

Map<String,String> map = new Map();
map['username'] = 'canhuah';
map['password'] = 'a123456';

HttpUtil.post('user/login', (data) {

// _showMessage('登录 成功');
},
params: map,
errorCallback: (msg) {
// _showMessage(msg);
});
}

具体HttpUtil类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import 'dart:async';
import 'package:http/http.dart' as http;

import 'dart:convert';

/*数据接口类型errorCode>0是接口请求成功
{
"data": ...,
"errorCode": 0,
"errorMsg": ""
}
*/

class Api {
//这个BaseUrl自己更改
static const String BaseUrl ="http://www.wanandroid.com/";
}

//这里只封装了常见的get和post请求类型
class HttpUtil {
static const String GET = "get";
static const String POST = "post";

static void get(String url, Function callback,
{Map<String, String> params,
Map<String, String> headers,
Function errorCallback}) async {
//偷懒..
if (!url.startsWith("http")) {
url = Api.BaseUrl + url;
}

if (params != null && params.isNotEmpty) {
StringBuffer sb = new StringBuffer("?");
params.forEach((key, value) {
sb.write("$key" + "=" + "$value" + "&");
});
String paramStr = sb.toString();
paramStr = paramStr.substring(0, paramStr.length - 1);
url += paramStr;
}
await _request(url, callback,
method: GET,
headers: headers,
errorCallback: errorCallback);
}

static void post(String url, Function callback,
{Map<String, String> params,
Map<String, String> headers,
Function errorCallback}) async {
if (!url.startsWith("http")) {
url = Api.BaseUrl + url;
}
await _request(url, callback,
method: POST,
headers: headers,
params: params,
errorCallback: errorCallback);
}

static Future _request(String url, Function callback,
{String method,
Map<String, String> headers,
Map<String, String> params,
Function errorCallback}) async {
String errorMsg;
int errorCode;
var data;
try {
Map<String, String> headerMap = headers == null ? new Map() : headers;
Map<String, String> paramMap = params == null ? new Map() : params;

http.Response res;
if (POST == method) {
res = await http.post(url, headers: headerMap, body: paramMap);
} else {
res = await http.get(url, headers: headerMap);
}

if (res.statusCode != 200) {
errorMsg = "网络请求错误,状态码:"+res.statusCode.toString();

_handError(errorCallback, errorMsg);
return;
}

//以下部分可以根据自己业务需求封装,这里是errorCode>=0则为请求成功,data里的是数据部分
//记得Map中的泛型为dynamic
Map<String, dynamic> map = json.decode(res.body);

errorCode = map['errorCode'];
errorMsg = map['errorMsg'];
data = map['data'];

// callback返回data,数据类型为dynamic
//errorCallback中为了方便我直接返回了String类型的errorMsg
if (callback != null) {
if (errorCode >= 0) {
callback(data);
} else {
_handError(errorCallback, errorMsg);
}
}
} catch (exception) {
_handError(errorCallback, exception.toString());
}
}


static void _handError(Function errorCallback,String errorMsg){
if (errorCallback != null) {
errorCallback(errorMsg);
}
print("errorMsg :"+errorMsg);
}
}