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);
  }
}

参考

相关推荐
0wioiw02 小时前
Flutter基础(FFI)
flutter
Georgewu9 天前
【HarmonyOS 5】鸿蒙跨平台开发方案详解(一)
flutter·harmonyos
爱吃鱼的锅包肉9 天前
Flutter开发中记录一个非常好用的图片缓存清理的插件
flutter
张风捷特烈10 天前
每日一题 Flutter#13 | build 回调的 BuildContext 是什么
android·flutter·面试
恋猫de小郭10 天前
Flutter 又双叒叕可以在 iOS 26 的真机上 hotload 运行了,来看看又是什么黑科技
android·前端·flutter
QC七哥10 天前
跨平台开发flutter初体验
android·flutter·安卓·桌面开发
小喷友10 天前
Flutter 从入门到精通(水)
前端·flutter·app
恋猫de小郭11 天前
Flutter 里的像素对齐问题,深入理解为什么界面有时候会出现诡异的细线?
android·前端·flutter
tbit11 天前
dart私有命名构造函数的作用与使用场景
flutter·dart