flutter之从零开始搭建(三)之 网络请求

简介: flutter之从零开始搭建(三)之 网络请求

flutter从零开始搭建系列:



项目还是在原来的基础上搭建,具体的可以看上面的连接


这次,我们来介绍下网络请求,并且将请求到的数据设置到ListView列表中。老规矩,先来看下效果图


image.png

页面看起来不错吧,在动手之前还是得说一下,首页数据来自wanandroid提供,毕竟用了别人的东西就得标明。


实战



flutter请求网络有两种,一种是http请求,一种是HttpClient请求,下面来分别来使用一下。


http方式

在使用http方式请求网络时,需要导入http包


//导入网络请求相关的包
import 'package:http/http.dart' as http; 
void _pullNet()  {
    http.get("http://www.wanandroid.com/project/list/1/json?cid=1")
        .then((http.Response response) {
             var convertDataToJson = JSON.decode(response.body);
             convertDataToJson = convertDataToJson["data"]["datas"];
             //打印请求的结果
             print(convertDataToJson);
             //更新数据
             setState(() {
                data = convertDataToJson;
             });
    });
 }
复制代码

httpClient方式


需要导入httpClient包


import 'dart:io';
void _httpClient() async {
    var responseBody;
    var httpClient = new HttpClient();
    var request = await httpClient.getUrl(
        Uri.parse("http://www.wanandroid.com/project/list/1/json?cid=1"));
    var response = await request.close();
    //判断是否请求成功
    if (response.statusCode == 200) {
      //拿到请求的数据
      responseBody = await response.transform(utf8.decoder).join();
      //解析json,拿到对应的jsonArray数据
      var convertDataToJson = jsonDecode(responseBody)["data"]["datas"];
      //更新数据
      setState(() {
        data = convertDataToJson;
      });
    } else {
      print("error");
    }
  }
复制代码


知道了网络请求的概念,那么,我们先来写下界面


ListView界面布局


打开HomePage,


import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new HomeState();
  }
}
 @override
 Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      body: new ListView(
          children: <Widget>[
            _getItem2(),
            _getItem2()
          ]),
    );
  }
  Widget _getItem2() {
    return new Card(child: new Padding(
      padding: const EdgeInsets.all(10.0), child: _getRowWidget2(),),
      elevation: 3.0,
      margin: const EdgeInsets.all(10.0),);
  }
  Widget _getRowWidget2() {
    return new Row(children: <Widget>[
      new Flexible(
          flex: 1,
          fit: FlexFit.tight, //和android的weight=1效果一样
          child: new Stack(children: <Widget>[
            new Column(children: <Widget>[
              new Text("title".trim(),
                  style: new TextStyle(color: Colors.black, fontSize: 20.0,),
                  textAlign: TextAlign.left),
              new Text("desc", maxLines: 3,)
            ],)
          ],)
      ),
      new ClipRect(child: new FadeInImage.assetNetwork(
        placeholder: "images/ic_shop_normal.png",
        image: "images/ic_shop_normal.png",
        width: 50.0,
        height: 50.0,
        fit: BoxFit.fitWidth,),),
    ],);
  }
复制代码


效果如下


image.png


ListView感觉看起来像是Android中的ScrollView+LineaLayout.vertical。


flutter的布局其实是个特别头疼的问题,widget特别多,没有android那么方便,也没有react-native的flex布局方便,迷之缩进更让人想删除widget都变得特别的困难,所以,在做布局这部分,我们尽可能的将widget做成分割出来,做成一个个的方法widget,然后组合起来。


数据填充


我们看到ListView接收的是一个widget数组,后台返回给我们jsonArray数据的时候,我们完全可以使用map来遍历数据,然后返回widget给Listview的children。


flutter是有生命周期的,大致生命周期可以分为

  • initState : 初始化widget的时候调用,只会调用一次。
  • build : 初始化之后开始绘制界面,当setState触发的时候会再次被调用
  • didUpdateWidget : 当触发setState时,会被调用
  • dispose : 页面销毁的时候调用


如果把他们和react-native进行分类看的话,下面是个对比


flutter react native
initState Mount等函数
didUpdateWidget update等函数
dispose Unmount等函数


所以,我们在请求网络的时候,将数据请求放在initState进行处理,下面贴出代码。


import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; //导入网络请求相关的包
class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new HomeState();
  }
}
class HomeState extends State<HomePage> {
 //数据源
  List data;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _pullNet();
  }
  void _pullNet() async {
    await http.get("http://www.wanandroid.com/project/list/1/json?cid=1")
        .then((http.Response response) {
      var convertDataToJson = JSON.decode(response.body);
      convertDataToJson = convertDataToJson["data"]["datas"];
      print(convertDataToJson);
      setState(() {
        data = convertDataToJson;
      });
    });
  }
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      body: new ListView(
          children:  _getItem() ),
    );
  }
   List<Widget> _getItem() {
    return data.map((item) {
      return new Card(child: new Padding(
        padding: const EdgeInsets.all(10.0), child: _getRowWidget(item),),
        elevation: 3.0,
        margin: const EdgeInsets.all(10.0),);
    }).toList();
  }
  Widget _getRowWidget(item) {
    return new Row(children: <Widget>[
      new Flexible(
          flex: 1,
          fit: FlexFit.tight, //和android的weight=1效果一样
          child: new Stack(children: <Widget>[
            new Column(children: <Widget>[
              new Text("${item["title"]}".trim(),
                  style: new TextStyle(color: Colors.black, fontSize: 20.0,),
                  textAlign: TextAlign.left),
              new Text("${item["desc"]}", maxLines: 3,)
            ],)
          ],)
      ),
      new ClipRect(child: new FadeInImage.assetNetwork(
        placeholder: "images/ic_shop_normal.png",
        image: "${item['envelopePic']}",
        width: 50.0,
        height: 50.0,
        fit: BoxFit.fitWidth,),),
    ],);
  }
复制代码


然后我们来看下效果图


image.png

相信大家看到了一闪而过的红色报警图,虽然不影响最后的显示效果,但是,我们必须得去处理。


在控制台中,我看到了这样的一句异常


The method 'map' was called on null
复制代码


看到map我们这才焕然大悟,因为网络请求是异步的,当前界面因为要执行build界面的绘制,导致我们在_getItem中map遍历data数据时是个空值,然后再异步请求成功后,setState又重新给data赋了值,然后触发了界面重新绘制,这时候,map遍历是有值,然后就出现了一下会出现异常,然后又好了的原因。


我们得想个办法,并且能优雅的去解决这个问题,对了,我们只需要在ListView中对data进行判空处理不就行了吗,如果为空的话,我们给他设置一个预加载页面,如果不为空的话,直接就当前现在的这套流程。


ok,思路有了,开始干吧


直接看build方法进行更改


@override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      body: new ListView(
          children: data != null ? _getItem() : _loading()),
    );
  }
  //预加载布局
  List<Widget> _loading() {
    return <Widget>[
      new Container(
        height: 300.0, child: new Center(child:
      new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          new CircularProgressIndicator(
            strokeWidth: 1.0,),
          new Text("正在加载"),
        ],)),)
    ];
  }
复制代码


然后我们再来看看效果图


image.png

目录
打赏
0
0
0
0
5
分享
相关文章
Flutter&鸿蒙next 封装 Dio 网络请求详解:登录身份验证与免登录缓存
本文详细介绍了如何在 Flutter 中使用 Dio 封装网络请求,实现用户登录身份验证及免登录缓存功能。首先在 `pubspec.yaml` 中添加 Dio 和 `shared_preferences` 依赖,然后创建 `NetworkService` 类封装 Dio 的功能,包括请求拦截、响应拦截、Token 存储和登录请求。最后,通过一个登录界面示例展示了如何在实际应用中使用 `NetworkService` 进行身份验证。希望本文能帮助你在 Flutter 中更好地处理网络请求和用户认证。
213 1
flutter:文件操作与网络请求 (十五)
本文介绍了 Dart 语言中文件操作与网络请求的相关知识,包括 Future 的使用、异步请求的处理以及 async 和 await 的应用。通过示例代码展示了如何实现延时操作、处理网络请求及解析 JSON 数据。
|
5月前
|
Flutter Image从网络加载图片刷新、强制重新渲染
Flutter Image从网络加载图片刷新、强制重新渲染
196 1
【Flutter前端技术开发专栏】Flutter中的网络请求与数据处理
【4月更文挑战第30天】本文介绍了Flutter开发中的网络请求和数据处理。 Flutter开发者可选择http(官方库)或dio(功能更强大)进行网络请求。http库简单易用,dio支持更多功能如拦截器。数据处理涉及JSON和XML解析,数据存储可选SharedPreferences或Hive,数据传递推荐使用InheritedWidget或Provider状态管理库。了解这些知识点能提升Flutter开发效率。
208 0
【Flutter前端技术开发专栏】Flutter中的网络请求与数据处理
【Flutter前端技术开发专栏】Flutter中的图片、视频与网络资源加载
【4月更文挑战第30天】Flutter是谷歌的开源前端框架,因其高性能、流畅UI和多端运行能力受开发者喜爱。本文聚焦于Flutter中的资源加载:使用`Image`组件加载静态、网络和本地图片;通过`video_player`库加载和播放视频;利用`http`包进行网络资源请求。掌握这些技巧将有助于提升Flutter应用的开发效率和质量。
65 0
【Flutter前端技术开发专栏】Flutter中的图片、视频与网络资源加载
Flutter的网络请求:使用Dart进行HTTP请求的技术详解
【4月更文挑战第26天】了解Flutter网络请求,本文详述使用Dart进行HTTP请求
带你读《深入浅出Dart》二十九、Flutter网络请求(1)
带你读《深入浅出Dart》二十九、Flutter网络请求(1)
104 0
带你读《深入浅出Dart》二十九、Flutter网络请求(2)
带你读《深入浅出Dart》二十九、Flutter网络请求(2)
103 0
《深入浅出Dart》Flutter网络请求
Flutter网络请求 网络请求是移动应用开发中常见的任务之一,Flutter提供了强大且易于使用的网络请求库,使得我们能够轻松地与服务器进行通信。我们将探讨不同类型的网络请求、错误处理、异步操作以及如何解析和处理响应数据。
230 0
Flutter常用的网络库
Flutter 有许多网络请求库可供选择,本回答将介绍其中几个比较常用的库,并附上其实现方案和示例代码。
Flutter常用的网络库

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等