pubspec 包含:
之前写的页面网络请求是用的http框架,其实还有一个更加普遍使用的框架dio,那么我们在dependencies - flutter - SDK 下面添加dio: ^4.0.1
(dio以及版本号),这里的缩进需要对齐。这里带着^
表示大版本不变的区间的写法,相当于4.0.1 <= 版本号 < 5.0.0。dio: 4.0.1
,如果不带^那么就是指定版本号。如果是dio: any
那么就是任意版本。如果是"dio: >3.0.1"
就是大于3.0.1(不包含)的版本。
pub get 之后就可以使用dio了,这里请求一下百度然后打印一下值。
import 'package:dio/dio.dart';
String _data = "0";
void main() {
dioDemo();
// print("A");
}
void dioDemo() {
final dio = Dio();
dio.get("https://www.baidu.com").then((value) => print(value));
}
然后发现这里确实打印出来了,说明请求成功了。
再来创建一个下载任务
// 发送网络请求
// 1. 创建dio 对象
final dio = Dio();
// 2. 下载数据
var downloadUrl = 'https://edu-files-1251502357.cos.ap-shanghai.myqcloud.com/CourseTeacher_2.8.1.13_DailyBuild.dmg';
dio.download(downloadUrl, '/Users/aibus/Desktop/腾讯课堂.dmg').then((value) => print(value)).whenComplete(() => print('结束了'));
运行后发现下载成功了
如果想要看到下载进度,那么就可以使用ProgressCallback。 .
dio.download(downloadUrl, '/Users/aibus/Desktop/腾讯课堂.dmg',onReceiveProgress: showDonwloadProgress).then((value) => print(value)).whenComplete(() => print('结束了'));
然后在showDonwloadProgress方法里面将值打印出来看看是什么东西。
void showDonwloadProgress(int count, int total) {
print('count:$count');
print('total:$total');
}
运行后根据打印可以得到,这里count代表已经下载的数据,而total则是总共有多少数据。
那么这里就可以算出百分比
void showDonwloadProgress(int count, int total) {
if (total != -1) {
print((count / total * 100).toStringAsFixed(0) + '%');
}
}
如果存在手机端就使用Directory,下载后就可以在打印出来的地址里面访问到了。
void download2(Dio dio, String url, String savePath) {
// 手机端
String iosPath = Directory.systemTemp.path + "/腾讯课堂.dmg";
print(iosPath);
dio
.download(url, (header) {
return iosPath;
}, onReceiveProgress: showDonwloadProgress)
.then((value) => print(value))
.whenComplete(() => print('结束了'))
.catchError((e) {
print('e');
});
}
之前的仿微信项目用的是http,那么接下来换成dio库。
这里先将之前的http封装起来。
在项目中先创建一个tools的package,然后创建一个http_manager文件
然后在里面封装http的方法,这样外界就不会直接用到库里面方法,而是用我们封装好的方法。
class HttpManager {
static Future get(Uri url, {Map? headers}) {
return http.get(url);
}
}
那么外界调用写成:
final response = await HttpManager.get(url);
接下来去pubspec里面添加dio库,然后pub get一下。
dio: ^4.0.1
然后封装dio方法
static Future get(String url) async {
return await Dio().get(url);
}
在dio里面返回的data直接就是map,所以外面可以直接用
final chatList = response.data['chat_list']
.map((item) => Chat.fromMap(item))
.toList();
static Future get(String url, {Map? queryParameters} ) async {
return await Dio().get(url,queryParameters: queryParameters);
}
接下来写post方法,那么我们就先写一个Dio单例对象。
static Dio? _dioInstance;
static Dio getDioInstance() {
if (_dioInstance == null) {
_dioInstance = Dio();
}
return _dioInstance!;
}
添加enum
enum HttpMethod {
Get,
POST,
}
然后在添加一个私有方法sendRequest来判断外界是调用get还是post方法,然后进行相应 的调用,然后根据不同的错误进行相对应的处理。
static Future _sendRequest(HttpMethod method,String url, {Map? queryParameters} ) async{
try {
switch (method) {
case HttpMethod.Get:
return await HttpManager.getDioInstance().get(url,queryParameters: queryParameters);
case HttpMethod.Get:
return await HttpManager.getDioInstance().post(url,queryParameters: queryParameters);
default:
throw Exception('请求方式错误');
}
} on DioError catch (e) {
print(e.message);
} on Exception catch (e) {
print(e.toString());
}
return null;
}
get方法就改成通过_sendRequest来调用。
static Future get(String url, {Map? queryParameters} ) async {
return await _sendRequest(HttpMethod.Get, url,queryParameters:queryParameters);
}
post方法里面要有data,那么就需要在_sendRequest方法里面添加可选参数data
static Future _sendRequest(HttpMethod method,String url, {Map? queryParameters,dynamic data} ) async{
try {
switch (method) {
case HttpMethod.GET:
return await HttpManager.getDioInstance().get(url,queryParameters: queryParameters);
case HttpMethod.POST:
return await HttpManager.getDioInstance().post(url,queryParameters: queryParameters,data: data);
default:
throw Exception('请求方式错误');
}
} on DioError catch (e) {
print(e.message);
} on Exception catch (e) {
print(e.toString());
}
return null;
}
post方法:
static Future post(String url, {Map? queryParameters,dynamic data} ) async {
return await _sendRequest(HttpMethod.POST, url,queryParameters:queryParameters,data: data);
}