Flutter 教程(七)网络请求

HttpClient

HttpClient 是 Dart 中自带的 HTTP 库。不过 HttpClient 在 Flutter 中用的比较少,这里只简单介绍一下它的用法,代码示例如下:

scss 复制代码
//创建一个HttpClient
HttpClient httpClient = HttpClient();
//打开Http连接
HttpClientRequest request = await httpClient.getUrl(
Uri.parse("https://www.baidu.com"),
);
//使用iPhone的UA
request.headers.add(
"user-agent",
"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1",
);
//等待连接服务器(会将请求信息发送给服务器)
HttpClientResponse response = await request.close();
//读取响应内容
_text = await response.transform(utf8.decoder).join();
//输出响应头
print(response.headers);

//关闭client后,通过该client发起的所有请求都会终止。
httpClient.close();

http 库

http 库是 Flutter 官方推荐使用的。首先我们需要引入 http 库。如下所示,在 pubspec.yaml 文件中声明依赖。

yaml 复制代码
dependencies:
  http: ^0.12.1

然后在代码中导入对应的包名,如下所示:

arduino 复制代码
import 'package:http/http.dart';

http 的使用示例如下所示:

  • get 请求
ini 复制代码
var client = http.Client();
var uri = Uri.parse('https://www.ptpress.com.cn/');
Map<String, String> header = {
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0)
  Gecko / 20100101 Firefox / 70.0',
};
http.Response response = await client.get(uri, headers: header);
print(utf8.decode(response.bodyBytes));
client.close();
  • post 请求
dart 复制代码
var client = http.Client();
Map<String, String> bodyMap = {
  'username': 'username',
  'password': 'password'
};
Map<String, String> headers = {
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) 
  Gecko / 20100101 Firefox / 70.0",
};
http.Response response = await
client.post('https://www.ptpress.com.cn/',
    headers: headers, body: bodyMap);
print(utf8.decode(response.bodyBytes));
client.close();

Json 解析

我们可以在 Android studio 中下载 JsonToDart 插件,通过这个插件我们可以把 Json 转化为 Dart 类。如下图所示:

生成对应的文件后,我们就可以使用生成的 Person.fromJson 来生成对应的 model 对象了。代码示例如下:

dart 复制代码
import 'dart:convert';
import 'package:http/http.dart' as http;

Future<Person> fetchPerson() async {
  final response = await http.get(Uri.parse('https://api.example.com/user/1'));
  
  if (response.statusCode == 200) {
    return Person.fromJson(jsonDecode(response.body));
  } else {
    throw Exception('Failed to load user');
  }
}

dio 库

dio库是Flutter中常用的三方HTTP库。要使用 dio 库,需要添加如下依赖:

yaml 复制代码
dependencies:
  dio: ^3.0.9
  • dio库的Get请求
dart 复制代码
try{
  Dio dio=new Dio();
  dio.options.headers={
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101
        Firefox/70.0"
  };
  Map<String,dynamic> queryParameters={
    'id':'123456',
    'book':'flutter'
  };
  Response response=await dio.get("https://www.ptpress.com.cn/",queryParameters: 
      queryParameters);
  print(response);
}catch(e){
  print(e);
}
  • dio库的Post请求
dart 复制代码
_dio_post() async{
  try{
    Dio dio=new Dio();
    dio.options.headers={
      "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101
          Firefox/70.0"
    };
    Map<String,dynamic> data={
      'username':'username',
      'password':'password'
    };
    Response response=await dio.post("https://www.ptpress.com.cn/",data: data);
    print(response);
  }catch(e){
   print(e);
  }
}
  • dio库下载图片
scss 复制代码
_dio_download() async{
  var sdDir = await getExternalStorageDirectory();
  Response response=await 
      Dio().download('https://cdn.ptpress.cn/pubcloud/null/
      cover/2021051442E8BF9.jpg', sdDir.path+'/image.jpg');
}
  • 使用dio库的FormData类上传多个文件
ini 复制代码
_dio_formData_uploadFile(File image1, File file2, File file3) async {
  Dio dio = new Dio();

  String path1 = image1.path;
  var name = path1.substring(path1.lastIndexOf("/") + 1, path1.length);

  String path2 = file2.path;
  var name2 = path1.substring(path2.lastIndexOf("/") + 1, path2.length);

  String path3 = file3.path;
  var name3 = path1.substring(path3.lastIndexOf("/") + 1, path3.length);
  Map<String, dynamic> fileMap = {
    "image1": await MultipartFile.fromFile(path1, filename: name),
    // 支持文件数组上传
    "files": [
      await MultipartFile.fromFile(path2, filename: name2),
      await MultipartFile.fromFile(path3, filename: name3),
    ],
  };
  FormData formData = new FormData.fromMap(fileMap);
  Response response = await dio.post("http://127.0.0.1/info", data: formData);
}
  • 分片下载
scss 复制代码
Future downloadWithChunks(
  url,
  savePath, {
  ProgressCallback onReceiveProgress,
}) async {
  const firstChunkSize = 102;
  const maxChunk = 3;

  int total = 0;
  var dio = Dio();
  var progress = <int>[];

  createCallback(no) {
    return (int received, _) {
      progress[no] = received;
      if (onReceiveProgress != null && total != 0) {
        onReceiveProgress(progress.reduce((a, b) => a + b), total);
      }
    };
  }

  Future<Response> downloadChunk(url, start, end, no) async {
    progress.add(0);
    --end;
    return dio.download(
      url,
      savePath + "temp$no",
      onReceiveProgress: createCallback(no),
      options: Options(
        headers: {"range": "bytes=$start-$end"},
      ),
    );
  }

  Future mergeTempFiles(chunk) async {
    File f = File(savePath + "temp0");
    IOSink ioSink= f.openWrite(mode: FileMode.writeOnlyAppend);
    for (int i = 1; i < chunk; ++i) {
      File _f = File(savePath + "temp$i");
      await ioSink.addStream(_f.openRead());
      await _f.delete();
    }
    await ioSink.close();
    await f.rename(savePath);
  }

  Response response = await downloadChunk(url, 0, firstChunkSize, 0);
  if (response.statusCode == 206) {
    total = int.parse(
        response.headers.value(HttpHeaders.contentRangeHeader).split("/").last);
    int reserved = total -
        int.parse(response.headers.value(HttpHeaders.contentLengthHeader));
    int chunk = (reserved / firstChunkSize).ceil() + 1;
    if (chunk > 1) {
      int chunkSize = firstChunkSize;
      if (chunk > maxChunk + 1) {
        chunk = maxChunk + 1;
        chunkSize = (reserved / maxChunk).ceil();
      }
      var futures = <Future>[];
      for (int i = 0; i < maxChunk; ++i) {
        int start = firstChunkSize + i * chunkSize;
        futures.add(downloadChunk(url, start, start + chunkSize, i + 1));
      }
      await Future.wait(futures);
    }
    await mergeTempFiles(chunk);
  }
}

参考

相关推荐
LawrenceLan1 小时前
Flutter 零基础入门(九):构造函数、命名构造函数与 this 关键字
开发语言·flutter·dart
一豆羹2 小时前
macOS 环境下 ADB 无线调试连接失败、Protocol Fault 及端口占用的深度排查
flutter
行者962 小时前
OpenHarmony上Flutter粒子效果组件的深度适配与实践
flutter·交互·harmonyos·鸿蒙
行者965 小时前
Flutter与OpenHarmony深度集成:数据导出组件的实战优化与性能提升
flutter·harmonyos·鸿蒙
小雨下雨的雨5 小时前
Flutter 框架跨平台鸿蒙开发 —— Row & Column 布局之轴线控制艺术
flutter·华为·交互·harmonyos·鸿蒙系统
小雨下雨的雨6 小时前
Flutter 框架跨平台鸿蒙开发 —— Center 控件之完美居中之道
flutter·ui·华为·harmonyos·鸿蒙
小雨下雨的雨6 小时前
Flutter 框架跨平台鸿蒙开发 —— Icon 控件之图标交互美学
flutter·华为·交互·harmonyos·鸿蒙系统
小雨下雨的雨6 小时前
Flutter 框架跨平台鸿蒙开发 —— Placeholder 控件之布局雏形美学
flutter·ui·华为·harmonyos·鸿蒙系统
行者967 小时前
OpenHarmony Flutter弹出菜单组件深度实践:从基础到高级的完整指南
flutter·harmonyos·鸿蒙
前端不太难7 小时前
Flutter / RN / iOS,在长期维护下的性能差异本质
flutter·ios