Flutter如何做到网络请求(多个网络请求)完成之后再加载页面

很多时候我们有这样一个需求,需要在网络请求完了之后再去渲染页面,尤其是在一个界面有多个相关网络请求的时候需要处理。
这里不得不提到一个系统的组件FutureBuilder,我们直接来看用法。

单网络请求:

 @override
  Widget buildWidget(BuildContext context, Store<UserState> store) {
    // TODO: implement buildWidget

    return Scaffold(
      body: FutureBuilder(
          future: _futureBuilderFuture,
          builder: (BuildContext context, AsyncSnapshot snapShot) {
            print('connectionState:${snapShot.connectionState}');
            if (snapShot.connectionState == ConnectionState.waiting) {
              return Text('Loading...');
            } else if (snapShot.connectionState == ConnectionState.done) {
              print(snapShot.hasError);
              print('data:${snapShot.data}');
              if (snapShot.hasError) {
                return Text('Error: ${snapShot.error}');
              }

              return ListView(
              ...

其中第一个参数 future对应的是一个具有Future返回值的方法,这个方法可以是一个网络请求,比如

 Future<CommonModel> fetchPost() async {
    final response = await http.get('http://www.devio.org/io/flutter_app/json/test_common_model.json');
    Utf8Decoder utf8decoder = Utf8Decoder(); //fix 中文乱码
    var result = json.decode(utf8decoder.convert(response.bodyBytes));
    return CommonModel.fromJson(result);
  }

那我们写法是

  future: fetchPost(),

避免重复网络请求:

但是这样写会有一个问题,那就是当我们调用setstate的时候,将会刷新整个FutureBuilder,结果会是fetchPost这个方法会调用多次,造成了不必要的请求和资源浪费。所以我们建议这样写

  var _futureBuilderFuture;
  @override
  void initState() {
    _futureBuilderFuture = getDatas();
    super.initState();
  }

引用的时候

  future: _futureBuilderFuture,

这样当我们调用setstate的时候,就不会有多次网络请求了

下来还有个问题,刚才是界面只有一个网络请求,那么假如有多个呢,写法如下:

  Future getDatas() async {
    
    return Future.wait([getDelegationData(), getData()]);
  }

多网络请求:

其中getDelegationData ,getData是两个单独的网络请求,写法如下

 Future getData() async {
    var data = {
      'iReq': "BTC_USDT",
    };
  TradeInfo response = await TradeService.getData(this, data.toString());
}

getDelegationData一样,不再给出,这样的话等两个请求都结束之后会返回一个新的Future到我们的FutureBuilder

   if (snapShot.connectionState == ConnectionState.waiting) {
              return Text('Loading...');
            } else if (snapShot.connectionState == ConnectionState.done) {
              print(snapShot.hasError);
              print('data:${snapShot.data}');
              if (snapShot.hasError) {
                return Text('Error: ${snapShot.error}');
              }

这里的话就用到了snapShot的几种状态,用来判断网络请求处于哪一个阶段,等待(请求中),done完成,包括如果请求有异常的话,我们可以打印出来 return Text(‘Error: ${snapShot.error}’);

注意事项:

这里有一个情况就是我们在调用Future.wait([getDelegationData(), getData()]);的时候,请求网络的顺序是按参数的先后顺序执行的,先走getDelegationData请求,再走getData,但是返回数据结果的顺序却不能保证,因为是根据请求需要的时间决定的,异步的,所以我们尽量把数据处理放在ConnectionState.done之后再处理。

多网络请求如何控制顺序:

另外如果你的网络请求有逻辑关系,比如第一个接口的返回值要当做第二个接口的请求参数,那么写法如下

Future testThen2()  asyn {
  Future getDatas() async {
  return getDelegationData().then((e){
    getData();
  });
  }
// 请求顺序是从外层到里层即 getDatas=====getDelegationData===getData

以上over,有不足之处请提出改正

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
要实现异步请求网络数据并显示加载中demo,我们可以使用Flutter框架的http插件和状态管理来完成。 首先,我们需要在pubspec.yaml文件中添加http插件的依赖。 ``` dependencies: flutter: sdk: flutter http: ^0.13.0 ``` 然后,在需要显示加载中的页面中,创建一个有状态的组件。在该组件的状态中定义一个布尔值isLoading来表示数据是否正在加载中。 ```dart import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class LoadingDemo extends StatefulWidget { @override _LoadingDemoState createState() => _LoadingDemoState(); } class _LoadingDemoState extends State<LoadingDemo> { bool isLoading = false; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Loading Demo'), ), body: Center( child: isLoading ? CircularProgressIndicator() : RaisedButton( child: Text('加载数据'), onPressed: () { fetchData(); }, ), ), ); } void fetchData() async { setState(() { isLoading = true; }); var response = await http.get('https://api.example.com/data'); if (response.statusCode == 200) { // 请求成功 var data = json.decode(response.body); // 处理数据 } else { // 请求失败 } setState(() { isLoading = false; }); } } ``` 在上述代码中,isLoading初始值为false,当点击加载数据按钮时,调用fetchData函数来请求数据。在请求数据时,将isLoading设置为true来显示加载动画,请求完成后再将其设置为false。 为了能够在Flutter中显示加载动画,我们使用了CircularProgressIndicator小部件,它会在屏幕中间显示一个圆形的进度指示器。 通过上述代码,我们可以实现一个简单的加载中demo,用于异步请求网络数据并显示加载状态。当点击加载数据按钮时,会显示加载动画,请求完成后隐藏加载动画。只需简单几步即可实现这样的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值