热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Flutter实现网络请求

Flutter网络请求使用的是Dio。Dio是一个强大易用的darthttp请求库,支持RestfulAPI、FormData、拦截器、请求取消、Cookie管理、文件上传下载…F
  • Flutter网络请求使用的是Dio。Dio是一个强大易用的dart http请求库,支持Restful API、FormData、拦截器、请求取消、COOKIE管理、文件上传/下载…

  • Flutter json数据解析是使用了json_serializable package包。它是一个自动化源代码生成器,可以为我们生成JSON序列化模板。由于序列化代码不再由我们手写和维护,我们将运行时产生JSON序列化异常的风险降至最低。

  • Flutter网络请求数据并且展示效果图:
    Flutter实现网络请求

  • 数据接口
    数据是使用的聚合数据的API,影讯API合集,大家可以注册个账号,申请使用一下,像这样
    Flutter实现网络请求

  • 添加依赖
    在pubspec.yaml文件中添加所需要的第三方依赖库

     environment:
      sdk: ">=2.1.0 <3.0.0"
    
     dependencies:
       flutter:
         sdk: flutter
     
       json_annotation: ^2.0.0
       connectivity: ^0.4.2
       dio: ^2.0.15
       event_bus:  ^1.0.3
       # The following adds the Cupertino Icons font to your application.
       # Use with the CupertinoIcons class for iOS style icons.
       cupertino_icons: ^0.1.2
     
     dev_dependencies:
       flutter_test:
         sdk: flutter
    
  • 网络请求过程分析

      	static netFetch(url,params,Map header,Options option,{noTip = false}) async {
      	//获取网络的连接状态,如果没有连接网络,返回NETWORK_ERROR
         var cOnnectivityResult= await (new Connectivity().checkConnectivity());
         if(cOnnectivityResult== ConnectivityResult.none) {
           return new ResultData(Code.errorHandleFunction(Code.NETWORK_ERROR, "", noTip),false,Code.NETWORK_ERROR);
         }
         //请求头存放集合
         Map headers = new HashMap();
         if(header != null) {
           headers.addAll(header);
         }
     	//option存放请求的一些配置信息
         if(option != null) {
           option.headers = headers;
         }else {
           //get请求
           option = new Options(method:'get');
           option.headers = headers;
         }
         //超时时间15000ms
         option.cOnnectTimeout= 15000;
     	//创建dio对象
         Dio dio = new Dio();
         Response response;
         try{
           //执行网络请求,await和async配合使用,表示这是一个异步耗时操作
           //执行结果不会立马返回。
           respOnse= await dio.request(url,data: params,options: option);
         }on DioError catch(e) {
           //异常处理
           ....
           return new ResultData(Code.errorHandleFunction(errorResponse.statusCode, e.message, noTip), false, errorResponse.statusCode);
         }
         try{
             if(response.statusCode == 200 || response.statusCode == 201) {
               //网络请求成功
               return await new ResultData(response.data, true, Code.SUCCESS,headers: response.headers);
           	 }
          }catch(e) {
     	  //异常处理
           print('返回参数' + e.toString() + url);
           return new ResultData(response.data, false, response.statusCode,headers: response.headers);
         }
         return new ResultData(Code.errorHandleFunction(response.statusCode, "", noTip), false, response.statusCode);
       }
    

    这个是最底层类封装了一个静态的请求方法,直接调用dio的request方法进行网路请求,很简单。

       //如果这个是耗时方法,就会用async标记,耗时操作用await标记,表示是一个异步操作。
       static getTodayFilmListDao() async {
       	//获取请求的url
         String url = Address.getTodayFilmList();
         //调用上面封装的网络请求方法进行网络请求
         var res = await HttpManager.netFetch(url, null, null, null);
         if(res != null && res.result) {
           var data = res.data;
           if(data == null || data.length == 0) {
             return await new DataResult([],true);
           }
           //网络请求成功,进行数据解析
           var respOnse= TodayFilmResponse.fromJson(data);
           //返回数据
           return await new DataResult(response.result,true);
         }else {
           return await new DataResult(null,false);
         }
       }
    

    获取url方法很简单,就是字符串拼接了一下

      static getTodayFilmList() {
         return "${host}movie/movies.today?cityid=1&dtype=&key=713a408e855352d913806ef1e3ce3c33";
       }
    
  • 下面分析一下json数据解析过程。
    如上所说,json解析使用的是json_serializable package包。它是一个自动化源代码生成器,可以为我们生成JSON序列化模板。
    网络请求获取到的json数据是这样的

     		{
     			"movieId":"135808",
     			"movieName":"新喜剧之王",
     			"pic_url":"http:\/\/img5.mtime.cn\/mt\/2019\/02\/02\/113216.53857992_182X243X4.jpg"
     		},
    

    TodayFilmBean类

     	//TodayFilmBean.g.dart将在我们运行生成命令之后自动生成
     	part 'TodayFilmBean.g.dart';
     	
     	//这个标注是告诉生成器,这个类是要生成的Model类
     	@JsonSerializable()
     	class TodayFilmBean{
     	  String movieId;
     	  String movieName;
     	  String pic_url;
     	  
     	   //构造函数
     	  TodayFilmBean(this.movieId,this.movieName,this.pic_url);
     	  
     	  //json转换为bean对象
     	  factory TodayFilmBean.fromJson(Map json) => _$todayFilmBeanFromJson(json);
     	  
     	  //bean对象转换为json
     	  Map toJson() => _$todayFilmBeanToJson(this);
     	}
    

    生成的TodayFilmBean.g.dart类是这样的

     	part of 'TodayFilmBean.dart';
     	
     	//json转换为bean对象
     	TodayFilmBean _$todayFilmBeanFromJson(Map json) {
     	  return TodayFilmBean(json['movieId'] as String,json['movieName'] as String,
     	      json['pic_url'] as String);
     	}
     	
     	//bean对象转换为json
     	Map _$todayFilmBeanToJson(TodayFilmBean instance) =>
     	     {
     	      'movieId': instance.movieId,
     	      'movieName': instance.movieName,
     	      'pic_url':instance.pic_url
         };
    

    有两种运行代码生成器的方法:
    1.一次性生成
    通过在我们的项目根目录下运行flutter packages pub run build_runner build,我们可以在需要时为我们的model生成json序列化代码。这触发了一次性构建,它通过我们的源文件,挑选相关的并为它们生成必要的序列化代码。

    虽然这非常方便,但如果我们不需要每次在model类中进行更改时都要手动运行构建命令的话会更好。

    2.持续生成
    使用_watcher_可以使我们的源代码生成的过程更加方便。它会监视我们项目中文件的变化,并且在需要时自动构建必要的文件。我们可以通过flutter packages pub run build_runner watch 在项目根目录下运行来启动_watcher_。

    只需启动一次观察器,然后并让它在后台运行,这是安全的。

    执行序列化只需执行

     //把json数据转化为了bean对象
     var filmBean = TodayFilmBean.fromJson(json); 
    
  • 使用GridView最终展示结果

       DataResult dataResult;
       List mData = [];
       
       //当StatefulWiget被嵌入此view树中,就会为此widget创建State对象
       //当State对象被创建了,frameWork就会调用initState()方法
       @override
       void initState() {
         //初始化数据
         getTodayFilm();
         super.initState();
       }
       
       
       void getTodayFilm() async {
         //这是一个异步操作,结果返回有一定延迟
         dataResult = await TodayDao.getTodayFilmListDao();
         //调用setState方法会通知framework控件状态有变化,它会立马触发
         //State的build方法更新widget状态
         setState(() {
           mData = dataResult.data;
         });
       }
    

    上面是初始化网络请求,在请求到数据后,调用setState刷新UI

     	  //State的build方法,调用setState方法后,此方法就会被触发
     	  //用来刷新UI
     	  @override
     	  Widget build(BuildContext context) {
     	
     	    return Scaffold(
     	      appBar: AppBar(
     	
     	        title: Text(widget.title),
     	      ),
     	      
     		  //如果mData.length == 0,展示一个loading框,否则展示数据
     	      body: mData.length == 0
     	          ? new Center(child: new CircularProgressIndicator()):
     	          //创建GridView对象
     	      	  new GridView.builder(
     	
     	          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
     	              crossAxisCount: 3, //每行2个
     	              mainAxisSpacing: 1.0, //主轴(竖直)方向间距
     	              crossAxisSpacing: 1.0, //纵轴(水平)方向间距
     	              childAspectRatio: 0.7 //纵轴缩放比例
     	          ),
     			  //item数量
     	          itemCount:mData.length,
    
     			  //创建每个item
     	          itemBuilder: (BuildContext context,int index) {
     	            return _getWidget(index);
     	          }),
     	    );
     	  }
    
       _getWidget(int index) {
         //添加要展示的item内容
           return new Column(
             children: [
               new Expanded(child: new CardItem(color: Colors.black12,child: _getChild(index)),flex: 8,),
               //显示网络请求文本
               new Expanded(child: new Text(mData[index].movieName,
                 textAlign: TextAlign.end,
                 maxLines: 1,
               ),
                   flex:1)
             ]);
       }
     
       _getChild(int i) {
         return new Padding(padding: new EdgeInsets.all(1.0),
         	//显示网络请求的图片
             child: new Image(image: NetworkImage(mData[i].pic_url)));
       }
    

    一个自定义的CardItem

     class CardItem extends StatelessWidget{
       final Widget child;
       final EdgeInsets margin;
       final Color color;
       final RoundedRectangleBorder shape;
       final double elevation;
     
       CardItem({@required this.color,this.child,this.elevation = 5.0,this.shape,this.margin});
     
       @override
       Widget build(BuildContext context) {
         EdgeInsets margin = this.margin;
         RoundedRectangleBorder shape = this.shape;
         Color color = this.color;
         margin ??= EdgeInsets.only(left: 2.0,top: 2.0,right: 2.0,bottom: 2.0);
         shape ??= new RoundedRectangleBorder(borderRadius: new BorderRadius.all(Radius.circular(4.0)));
         color ??= new Color(0xffeeff);
         return new Card(elevation: elevation,shape: shape,color: color,margin: margin,child: child,);
       }
     }
    

    好了,Flutter网络请求并且展示数据就这样实现的。
    最后附上demo地址:https://github.com/xinhuashi/flutter_http_demo.git


推荐阅读
  • ShiftLeft:将静态防护与运行时防护结合的持续性安全防护解决方案
    ShiftLeft公司是一家致力于将应用的静态防护和运行时防护与应用开发自动化工作流相结合以提升软件开发生命周期中的安全性的公司。传统的安全防护方式存在误报率高、人工成本高、耗时长等问题,而ShiftLeft提供的持续性安全防护解决方案能够解决这些问题。通过将下一代静态代码分析与应用开发自动化工作流中涉及的安全工具相结合,ShiftLeft帮助企业实现DevSecOps的安全部分,提供高效、准确的安全能力。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • Flutter第六章(BottomNavigationBar ,AppBar,TabBar ,TabController 以及案例)
    版权声明:本文为作者原创书籍。转载请注明作者和出处,未经授权,严禁私自转载,侵权必究!!!情感语录:如果你想得到从未拥有过的东西,那么你必须去做从未做过的事 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • MVC设计模式的介绍和演化过程
    本文介绍了MVC设计模式的基本概念和原理,以及在实际项目中的演化过程。通过分离视图、模型和控制器,实现了代码的解耦和重用,提高了项目的可维护性和可扩展性。详细讲解了分离视图、分离模型和分离控制器的具体步骤和规则,以及它们在项目中的应用。同时,还介绍了基础模型的封装和控制器的命名规则。该文章适合对MVC设计模式感兴趣的读者阅读和学习。 ... [详细]
  • macOS命令行创建Android模拟器
    macOS下不安装AndroidStudio使用VSCode来开发Flutter应用使用命令行创建和管理Android模拟器设备avdmanageravdmanager 是一种命令 ... [详细]
author-avatar
修月夕杨_433
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有