说点儿闲话
Flutter官方建议您使用 dio
来发起网络请求,在学习过程中,也尝试过用dart io
中的HttpClient
发起的请求,这里主要讲一下dio
的使用以及CookieJar
、CookieManager
管理cookie
。
dio
dio
是一个强大易用的dart http
请求库,支持Restful API
、FormData
、拦截器、请求取消、Cookie
管理、文件上传/下载……详情请查看 github dio
最新版本请查看:pub.dev dio
在pubspec.yaml文件里添加:
dio: ^3.x.x // 请使用pub上3.0.0分支的最新版本
创建一个Dio实例,并配置它
建议在项目中使用Dio单例,这样便可对同一个dio实例发起的所有请求进行一些统一的配置,比如设置公共header、请求基地址、超时时间等;
在这里,baseUrl
需要单独创建一个共用的BaseUrl.url
:
class BaseUrl {
// 配置默认请求地址
static String url = 'http://xxxxx/'; // 测试环境
}
BaseUrl.url
也方便后面Cookie
管理用到。
使用默认配置:
Dio dio \= Dio(); // 使用默认配置
// 配置dio实例
dio.options.baseUrl \= BaseUrl.url;
dio.options.connectTimeout \= 5000; //5s
dio.options.receiveTimeout \= 3000;
或者
// 通过传递一个 \`options\`来创建dio实例
Options options \= BaseOptions(
baseUrl: BaseUrl.url,
connectTimeout: 5000,
receiveTimeout: 3000,
);
Dio dio \= Dio(options);
发起请求及响应数据
发起一个GET
请求 :
Response response;
Dio dio \= Dio();
response \= await dio.get("/test?id=12&name=wendu")
print(response.data.toString());
// 请求参数也可以通过对象传递,上面的代码等同于:
response \= await dio.get("/test", queryParameters: {"id": 12, "name": "wendu"});
print(response.data.toString());
发起一个POST
请求:
response \= await dio.post("/test", data: {"id": 12, "name": "wendu"});
try {
Response response \= await dio.get("https://www.google.com");
print(response.data);
print(response.headers);
print(response.request);
print(response.statusCode);
} on DioError catch (e) {
//catch 提示
print('catch 提示: ' + e.toString());
} finally {
}
CookieJar 和 CookieManager
github CookieJar
pub.dev cookie_jar
github dio_cookie_manager
pub.dev dio_cookie_manager
在pubspec.yaml文件里添加:
cookie_jar: ^1.0.x #latest version
dio_cookie_manager: ^1.0.x #latest version
import 'package:flutter/material.dart';
import 'package:cookie_jar/cookie_jar.dart';
class Api {
static final CookieJar cookieJar = new CookieJar();
}
在项目中其他所有的dart文件中使用:
List cookies = [
new Cookie("xxx", xxx),
// ....
];
//Save cookies
Api.cookieJar.saveFromResponse(Uri.parse(BaseUrl.url), cookies);
//获取cookies
List cookies = Api.cookieJar.loadForRequest(Uri.parse(BaseUrl.url));
// print(cookies);
需要注意的是,一般我们的项目中登录接口调用成功后,后端会在cookie
中写入token
,所以登录请求前先建立CookieManager
来自动管理cookie:
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
dio.interceptors.add(CookieManager(await Api.cookieJar));
一开始,我在app中使用的上述方法存cookie,开发过程中都是flutter run
运行的,后来打包测试,发现后台杀掉app时,获取不到cookie了,这才注意到:
CookieJar
将cookie
保存在RAM
中,因此,如果应用程序退出,则将清除所有cookie
。
于是,改为使用下面的PersistCookieJar
。
PersistCookieJar
PersistCookieJar
将cookie保存在文件
中,因此,如果应用程序退出,则cookie始终存在,除非显式调用delete
。
将上述Api中的CookieJar()
改为PersistCookieJar
:
注意:在flutter中,传递给PersistCookieJar的路径必须有效(存在于电话中并具有写访问权限)。您可以使用 path_provider来获取正确的路径。
在pubspec.yaml文件里添加:
path\_provider: ^1.0.x #latest version
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:path_provider/path_provider.dart';
class Api {
//改为使用 PersistCookieJar,在文档中有介绍,PersistCookieJar将cookie保留在文件中,因此,如果应用程序退出,则cookie始终存在,除非显式调用delete
static PersistCookieJar _cookieJar;
static Future get cookieJar async {
// print(_cookieJar);
if (_cookieJar == null) {
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
print('获取的文件系统目录 appDocPath: ' + appDocPath);
_cookieJar = new PersistCookieJar(dir: appDocPath);
}
return _cookieJar;
}
}
在项目中其他所有的dart文件中使用改为:
List cookies = [
new Cookie("xxx", xxx),
// ....
];
//Save cookies
(await Api.cookieJar).saveFromResponse(Uri.parse(BaseUrl.url), cookies);
//获取cookies
List cookies = (await Api.cookieJar).loadForRequest(Uri.parse(BaseUrl.url));
// print(cookies);
建立CookieManager
来自动管理cookie
的代码不改变。
参考资料
dio
Http请求-Dio http库
github CookieJar
pub.dev cookie_jar
github dio_cookie_manager
pub.dev dio_cookie_manager
path_provider
Flutter用dio封装http网络请求,设置统一的请求地址、headers及处理返回内容