Flutter实现网络请求

作者 : 开心源码 本文共6183个字,预计阅读时间需要16分钟 发布时间: 2022-05-12 共219人阅读
  • Flutter网络请求使用的是Dio。Dio是一个强大易用的dart http请求库,支持Restful API、FormData、阻拦器、请求取消、Cookie管理、文件上传/下载…….

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

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

    在这里插入图片形容

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

    在这里插入图片形容

  • 增加依赖
    在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<String,String> 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<String,String> 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<String,dynamic> json) => _$todayFilmBeanFromJson(json);                    //bean对象转换为json          Map<String,dynamic> toJson() => _$todayFilmBeanToJson(this);        }生成的TodayFilmBean.g.dart类是这样的        part of 'TodayFilmBean.dart';                //json转换为bean对象        TodayFilmBean _$todayFilmBeanFromJson(Map<String,dynamic> json) {          return TodayFilmBean(json['movieId'] as String,json['movieName'] as String,              json['pic_url'] as String);        }                //bean对象转换为json        Map<String,dynamic> _$todayFilmBeanToJson(TodayFilmBean instance) =>            <String,dynamic> {              '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<TodayFilmBean> 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: <Widget>[          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地址: xinhuashi/flutter_http_demo.git

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Flutter实现网络请求

发表回复