首页 > 其他分享 >flutter入门系列教程<2>:Http请求库-dio的使用

flutter入门系列教程<2>:Http请求库-dio的使用

时间:2025-01-23 21:56:33浏览次数:3  
标签:dio Http 请求 final json response data flutter

文章目录

11.3 Http请求库-dio

本处示例来自:https://book.flutterchina.club/chapter11/dio.html

通过上一节介绍,我们可以发现直接使用HttpClient发起网络请求是比较麻烦的,很多事情得我们手动处理,如果再涉及到文件上传/下载、Cookie管理等就会非常繁琐。幸运的是,Dart社区有一些第三方http请求库,用它们来发起http请求将会简单的多,本节我们介绍一下目前人气较高的dio (opens new window)库。

dio是笔者维护的一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等。dio的使用方式随着其版本升级可能会发生变化,如果本节所述内容和最新dio功能有差异,请以最新的dio文档为准。

11.3.1 引入dio

引入dio:

dependencies:
  dio: ^x.x.x #请使用pub上的最新版本

导入并创建dio实例:

import 'package:dio/dio.dart';
Dio dio =  Dio();

接下来就可以通过 dio实例来发起网络请求了,注意,一个dio实例可以发起多个http请求,一般来说,APP只有一个http数据源时,dio应该使用单例模式。

11.3.2 通过dio发起请求

发起 GET 请求 :

Response response;
response=await dio.get("/test?id=12&name=wendu")
print(response.data.toString());

对于GET请求我们可以将query参数通过对象来传递,上面的代码等同于:

response=await dio.get("/test",queryParameters:{"id":12,"name":"wendu"})
print(response);

发起一个 POST 请求:

response=await dio.post("/test",data:{"id":12,"name":"wendu"})

发起多个并发请求:

response= await Future.wait([dio.post("/info"),dio.get("/token")]);

下载文件:

response=await dio.download("https://www.google.com/",_savePath);

发送 FormData:

FormData formData = FormData.from({
   "name": "wendux",
   "age": 25,
});
response = await dio.post("/info", data: formData)

如果发送的数据是FormData,则dio会将请求header的contentType设为“multipart/form-data”。

通过FormData上传多个文件:

FormData formData = FormData.from({
   "name": "wendux",
   "age": 25,
   "file1": UploadFileInfo(File("./upload.txt"), "upload1.txt"),
   "file2": UploadFileInfo(File("./upload.txt"), "upload2.txt"),
     // 支持文件数组上传
   "files": [
      UploadFileInfo(File("./example/upload.txt"), "upload.txt"),
      UploadFileInfo(File("./example/upload.txt"), "upload.txt")
    ]
});
response = await dio.post("/info", data: formData)

值得一提的是,dio内部仍然使用HttpClient发起的请求,所以代理、请求认证、证书校验等和HttpClient是相同的,我们可以在onHttpClientCreate回调中设置,例如:

(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
    //设置代理 
    client.findProxy = (uri) {
      return "PROXY 192.168.1.2:8888";
    };
    //校验证书
    httpClient.badCertificateCallback=(X509Certificate cert, String host, int port){
      if(cert.pem==PEM){
      return true; //证书一致,则允许发送数据
     }
     return false;
    };   
  };

注意,onHttpClientCreate会在当前dio实例内部需要创建HttpClient时调用,所以通过此回调配置HttpClient会对整个dio实例生效,如果应用需要多种代理或证书校验策略,可以创建不同的dio实例来分别实现。

怎么样,是不是很简单,除了这些基本的用法,dio还支持请求配置、拦截器等,官方资料比较详细,故本书不再赘述,详情可以参考dio主页:https://github.com/flutterchina/dio 。 下一节我们将使用dio实现一个分块下载器。

11.3.3 实例

我们通过Github开放的API来请求flutterchina组织下的所有公开的开源项目,实现:

在请求阶段弹出loading
请求结束后,如果请求失败,则展示错误信息;如果成功,则将项目名称列表展示出来。
代码如下:

class _FutureBuilderRouteState extends State<FutureBuilderRoute> {
  Dio _dio = Dio();

  @override
  Widget build(BuildContext context) {

    return Container(
      alignment: Alignment.center,
      child: FutureBuilder(
          future: _dio.get("https://api.github.com/orgs/flutterchina/repos"),
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            //请求完成
            if (snapshot.connectionState == ConnectionState.done) {
              Response response = snapshot.data;
              //发生错误
              if (snapshot.hasError) {
                return Text(snapshot.error.toString());
              }
              //请求成功,通过项目信息构建用于显示项目名称的ListView
              return ListView(
                children: response.data.map<Widget>((e) =>
                    ListTile(title: Text(e["full_name"]))
                ).toList(),
              );
            }
            //请求未完成时弹出loading
            return CircularProgressIndicator();
          }
      ),
    );
  }
}

实战:注意点

实战以https://api.codelife.cc/todayShici?lang=cn接口为例,大家可以直接访问该接口
接口返回格式如下(直接Android Studio的devTools可查看):
在这里插入图片描述

1.声明返回参数model

示例返回的model声明如下

// 返回的类字段
class PoetryData {
  final String author;
  final String content;
  final String dynasty;
  final String preface;
  final String quotes;
  final String reviews;
  final String title;
  final String translate;
  final String annotation;
  final String updateTime;
  final String createTime;

  PoetryData({
    required this.author,
    required this.content,
    required this.dynasty,
    required this.preface,
    required this.quotes,
    required this.reviews,
    required this.title,
    required this.translate,
    required this.annotation,
    required this.updateTime,
    required this.createTime,
  });

  factory PoetryData.fromJson(Map<String, dynamic> json) {
    return PoetryData(
      author: json['author'],
      content: json['content'],
      dynasty: json['dynasty'],
      preface: json['preface'],
      quotes: json['quotes'],
      reviews: json['reviews'],
      title: json['title'],
      translate: json['translate'],
      annotation: json['annotation'],
      updateTime: json['updateTime'],
      createTime: json['createTime'],
    );
  }
}

// 我的 - 诗词API测试
class PoetryResponse {
  final int code;
  final String msg;
  final PoetryData data;

  PoetryResponse({
    required this.code,
    required this.msg,
    required this.data,
  });

  factory PoetryResponse.fromJson(Map<String, dynamic> json) {
    return PoetryResponse(
      code: json['code'],
      msg: json['msg'],
      data: PoetryData.fromJson(json['data']),
    );
  }
}

2.请求接口

const apiUrl = 'https://api.codelife.cc/todayShici?lang=cn';
      final response = await dio.get(apiUrl);

3.渲染组件

主页面的全部代码如下:

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import '/utils/platform_check.dart';
import '/components/custom/tabBarFree.dart';
import '/model/mine/poetry.dart';
import 'package:intl/intl.dart';

// 我的 - 随机诗词 - iTab诗词源
class ITabPoetryPage extends StatefulWidget {
  const ITabPoetryPage({super.key});

  @override
  State<ITabPoetryPage> createState() => _ITabPoetryPageState();
}

class _ITabPoetryPageState extends State<ITabPoetryPage> {
  PoetryResponse? myResult;

  // 如果是web端,则不设置请求头,否则设置
  final dio = Dio(BaseOptions(
      headers: {
        if(!PlatformCheck.isWeb)
          'Content-Type': 'application/json',
        if(!PlatformCheck.isWeb)
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
      }
  ));

  @override
  void initState() {
    super.initState();
    debugPrint('init初始化,是否为web端:${PlatformCheck.isWeb}');
    getHttp();
  }

  Future<void> getHttp() async {
    try {
      // const apiUrl = 'https://v1.jinrishici.com/all.json';
      const apiUrl = 'https://api.codelife.cc/todayShici?lang=cn';
      final response = await dio.get(apiUrl);
      debugPrint('接口返回值: $response');
      setState(() {
        myResult = PoetryResponse.fromJson(response.data);
      });
    } catch (e) {
      debugPrint('报错啦啦啦啦:$e');
    }
  }

  Widget paddingWidget(Widget child) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: child,
    );
  }

  // 构建内容
  Widget buildText(String? data) {
    return data != null ? paddingWidget(Text(data)) : const Text('暂无数据');
  }

  // 刷新按钮
  Widget refreshBtn() {
    return OutlinedButton(
        onPressed: getHttp,
        child: const Text('今日诗词刷新')
    );
  }

  // 格式化时间
  String formatDateTime(String? dateTimeString) {
    if (dateTimeString == null) return '暂无时间数据';
    try {
      final dateTime = DateTime.parse(dateTimeString);
      final formatter = DateFormat('yyyy-MM-dd HH:mm:ss');
      return formatter.format(dateTime);
    } catch (e) {
      debugPrint('日期格式化错误: $e');
      return '日期格式化错误';
    }
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: FreeTabBar(
        topWidget: myResult != null
          ? Column(
              children: [
                refreshBtn(),
                const SizedBox(height: 10,),
                // 标题
                Text(myResult!.data.title),
                // 朝代 - 作者
                Text('${myResult!.data.dynasty} · ${myResult!.data.author}',),
                // 内容
                Text(myResult!.data.content),
              ],
            ) : refreshBtn(),
        bottomWidget: Column(
          children: [
            // 创建时间
            Text(formatDateTime(myResult?.data.createTime)),
          ],
        ),
        tabs: const ['译文', '注释', '引言', '评语', '引言'],
        children: [
          // 译文
          buildText(myResult?.data.translate),
          // 注释
          buildText(myResult?.data.annotation),
          // 引言
          buildText(myResult?.data.preface),
          // 评语
          buildText(myResult?.data.reviews),
          // 引语
          buildText(myResult?.data.quotes),
        ],
      ),
    );
  }
}

效果图如下:
在这里插入图片描述

标签:dio,Http,请求,final,json,response,data,flutter
From: https://blog.csdn.net/yan1915766026/article/details/145305787

相关文章

  • 关闭 Visual Studio 2022 的 Browser Link 功能
    http://blog.tool90.com/330.html 什么是BrowserLink功能?BrowserLink是VisualStudio的一个功能,它允许VisualStudio与正在运行的ASP.NET应用程序建立一个实时通信通道。这意味着您可以在不刷新浏览器的情况下立即查看代码更改的效果。这个功能在进行前端开发时非......
  • HTTPS 证书自动化运维:基础知识与重要性
    简介:随着互联网的飞速发展和网络安全威胁的日益增多,HTTPS(HyperTextTransferProtocolSecure)已经成为保护网站和用户数据安全的标准协议。HTTPS证书的管理和更新是确保网站安全性的关键步骤。然而,手动管理HTTPS证书既繁琐又容易出错,因此,证书的自动化运维变得尤为重要。这篇文......
  • HTTPS 证书自动化运维:使用Certbot来申请https证书实践指南
    简介在第一篇文章中,我们介绍了HTTPS证书的基础知识和自动化运维的重要性。本篇文章将进一步深入,提供具体的实践指南和案例分析,帮助您在实际操作中更有效地管理HTTPS证书,采用使用最广泛的证书Let’sEncrypt,实现自动化运维的最佳效果。一、HTTPS证书自动化运维实践指南1.......
  • HTTPS 证书自动化运维:展望未来发展趋势
    HTTPS证书自动化运维的发展趋势自动化程度进一步提升随着技术的发展,未来的HTTPS证书管理系统将更加自动化,减少人工干预,提高效率。自动签发、续订和部署将成为标准功能。这不仅减少了人为错误的可能性,还大大提高了管理效率。多云平台集成未来的证书管理系统将更好地集成到......
  • HTTPS 证书自动化运维:HTTPS 证书管理系统之使用指南
    简介在前三篇文章中,我们介绍了HTTPS证书的基础知识、自动化运维的重要性、功能与优势。本文将提供https证书管理系统的详细配置和使用指南,帮助您从注册到实际应用,全面掌握该系统的使用方法,页面顶部菜单有详细的【视频教程】和【图文教程】。一、注册账户配置邮箱访问https证......
  • HTTPS 证书自动化运维:HTTPS 证书管理系统之优势对比
    简介在前两篇文章中,我们探讨了HTTPS证书的基础知识、自动化运维的重要性以及具体的实践指南和案例分析。本文将详细介绍一款好用的HTTPS证书管理系统,展示其强大的功能和显著的优势,帮助企业和个人用户更高效地管理HTTPS证书。https证书管理系统功能概述自动签发HTTPS证......
  • Gradio + Transformers** 实现带记忆功能的对话系统完整代码示例
    以下是一个使用Gradio+Transformers实现带记忆功能的对话系统完整代码示例,无需额外数据库依赖:importgradioasgrimportnumpyasnpfromtransformersimportAutoTokenizer,AutoModelfromtypingimportDict,List,Tuple#-----------------初始化模型---......
  • flutter入门系列教程<一>:tab组件的灵活妙用
    文章目录说明区分TabBarView组件TabBarViewTabBar实例需求升级写在中间的tabbar组件封装组件组件说明组件用法示例常规的tabbar封装常规用法说明前提:假设你已初步了解了flutter和dart语言,并且知道怎么创建一个简单的项目;学习本文后,你将掌握:tab组件的用法;组件的......
  • Windows下,powershell实现自动编译生成Visual Studio项目
    windows平台、VS2019、x64、C++/C在进行生成编译版本,并输出版本时,常常会遇到多个工程编译,同时提取出所需的动态库dll、执行文件exe,并进行打包。每次进行编译和打包均需要手动操作,过于繁琐,所以这里通过一个powershell文件去执行自动编译,后续可以通过批处理或者其他的powershell......
  • 如何修改美化radio、checkbox的默认样式?
    修改和美化HTML中的radio和checkbox的默认样式,主要可以通过CSS和一些前端技巧来实现。下面是一个基本的步骤指南,以及一些示例代码,帮助你开始这个过程。步骤指南隐藏默认的输入元素:使用CSS的display:none;或visibility:hidden;(配合其他布局技巧)来隐藏默认的ra......