Flutter学习11 - Future 与 FutureBuilder

1、Future

  • 可以利用 Future 实现异步调用

1.1、Future 的两种形式

自定义一个结果类

class Response {
  String _data;

  Response(this._data);
}

自定义方法实现 Future

Future<Response> testFuture() {
  var random = Random();
  int randomNumber = random.nextInt(10);
  if (randomNumber % 2 == 0) {
    return Future.value(Response('success: 偶数 $randomNumber'));
  } else {
    return Future.error('error: 奇数 $randomNumber');
  }
}
(1) then - onError
void main() {
  testFuture().then((value) {
    print(value._data);
  }, onError: (e) {
    print('1、onError: $e');
  });
}
(2) then - catchError
void main() {
  testFuture().then((value) {
    print(value._data);
  }).catchError((e) {
    print('2、catchError: $e');
  });
(3) 注意:当 onError 与 catchError 同时存在,只会调用 onError
void main() {
  //注:当 onError 与 catchError 同时存在,只会执行 onError
  testFuture().then((value) {
    print(value._data);
  }, onError: (e) {
    print('3、onError: $e');
  }).catchError((e) {
    print('3、catchError: $e');
  });
}

1.2、Future.whenComplete

then - catchError - whenComplete 类似于 try - catch - finally

Future<String> testFutureWhenComplete() {
  var random = Random();
  int randomNumber = random.nextInt(10);
  if (randomNumber % 2 == 0) {
    return Future.value('success: 偶数 $randomNumber');
  } else {
    return Future.error('error: 奇数 $randomNumber');
  }
}
void main(){
  testFutureWhenComplete()
      .then(print)
      .catchError(print)
      .whenComplete(() {
    print('完成!!!');
  });
}

1.3、Future.timeout

Future<String> testFutureTimeout() {
  return Future.delayed(const Duration(seconds: 2), () {
    var random = Random();
    int randomNumber = random.nextInt(10);
    if (randomNumber % 2 == 0) {
      return Future.value('success: 偶数 $randomNumber');
    } else {
      return Future.error('error: 奇数 $randomNumber');
    }
  });
}
void main(){
  //TimeoutException after 0:00:01.000000: Future not completed
  // Done!!!
  testFutureTimeout()
      .timeout(const Duration(seconds: 1))
      .then(print)
      .catchError(print)
      .whenComplete(() {
    print('Done!!!');
  });
}

2、FutureBuilder

  • FutureBuilder 是一个将异步操作和异步UI结合在一起的控件

在这里插入图片描述

2.1、构造函数

FutureBuilder({Key key, Future<T> future, T initialData,  AsyncWidgetBuilder<T> builder })
initialDataFuture完成前的初始化数据
future异步操作,返回Future对象
builder异步UI
builder
  • builder函数接受两个参数BuildContext context 与 AsyncSnapshot snapshot,返回一个widget
final AsyncWidgetBuilder<T> builder;
typedef AsyncWidgetBuilder<T> = Widget Function(BuildContext context, AsyncSnapshot<T> snapshot);
AsyncSnapshot 包含信息
  • connectionState:表示与异步计算的连接状态,ConnectionState有四个值:none,waiting,active,done
none当前未连接到异步计算
waiting连接到异步计算等待交互
active异步计算进行中
done异步计算完成
  • data:异步计算接收到的最新数据
  • error:异步计算接收到的最新错误数据
  • hasData:检查是否包含非空数据
  • hasError:检查是否包含错误值

2.2、代码示例

在这里插入图片描述

FutureBuilderDemo.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class FutureBuilderDemo extends StatefulWidget {
  const FutureBuilderDemo({super.key});

  
  State<FutureBuilderDemo> createState() => _FutureBuilderDemoState();
}

class _FutureBuilderDemoState extends State<FutureBuilderDemo> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('FutureBuilder Demo'),
      ),
      body: FutureBuilder<PhoneEntity>(
        future: _doGet(),
        builder: (BuildContext context, AsyncSnapshot<PhoneEntity> snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none:
              return const Text('状态:无');
            case ConnectionState.waiting:
              //进度条
              return const Center(
                child: CircularProgressIndicator(),
              );
            case ConnectionState.active:
              return const Text('状态:激活');
            case ConnectionState.done:
              if (snapshot.hasError) {
                //失败
                return Text(
                  '${snapshot.error}',
                  style: const TextStyle(color: Colors.red),
                );
              } else {
                return Column(
                  children: [
                    Text('code: ${snapshot.data!.code}'),
                    Text('city: ${snapshot.data!.data!.city}'),
                    Text('province: ${snapshot.data!.data!.province}'),
                    Text('sp: ${snapshot.data!.data!.sp}'),
                  ],
                );
              }
          }
        },
      ),
    );
  }

  Future<PhoneEntity> _doGet() async {
    var url =
        Uri.parse('https://cx.shouji.360.cn/phonearea.php?number=17688888888');
    var response = await http.get(url);
    if (response.statusCode == 200) {
      //请求成功
      try {
        var json = response.body;
        var map = jsonDecode(json);
        var entity = PhoneEntity.fromJson(map);
        return Future.value(entity);
      } catch (e) {
        return Future.error('数据异常: ${e.toString()}');
      }
    } else {
      //请求失败
      return Future.error('请求失败 ! ! !');
    }
  }
}

/**********************/

///
/// Code generated by jsonToDartModel https://ashamp.github.io/jsonToDartModel/
///
class PhoneEntityData {
/*
{
  "province": "广东",
  "city": "广州",
  "sp": "联通"
}
*/

  String? province;
  String? city;
  String? sp;

  PhoneEntityData({
    this.province,
    this.city,
    this.sp,
  });

  PhoneEntityData.fromJson(Map<String, dynamic> json) {
    province = json['province']?.toString();
    city = json['city']?.toString();
    sp = json['sp']?.toString();
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['province'] = province;
    data['city'] = city;
    data['sp'] = sp;
    return data;
  }
}

class PhoneEntity {
/*
{
  "code": 0,
  "data": {
    "province": "广东",
    "city": "广州",
    "sp": "联通"
  }
}
*/

  int? code;
  PhoneEntityData? data;

  PhoneEntity({
    this.code,
    this.data,
  });

  PhoneEntity.fromJson(Map<String, dynamic> json) {
    code = json['code']?.toInt();
    data =
        (json['data'] != null) ? PhoneEntityData.fromJson(json['data']) : null;
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['code'] = code;
    if (data != null) {
      data['data'] = this.data!.toJson();
    }
    return data;
  }
}

main.dart

import 'package:flutter/material.dart';

import 'FutureBuilderDemo.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Leon Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const FutureBuilderDemo(),
    );
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/534965.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DHCP抓包分析

DHCP动态路由配置协议&#xff0c;是C/S架构&#xff0c;由DHCP服务器为客户端动态分配IP信息。 DHCP客户端首次接入网络数据交互过程&#xff1a; 如何解决IP地址的冲突&#xff1a; ▫ DHCP服务器端&#xff1a;收到DHCP DISCOVER报文时&#xff0c;给客户端分配IP地址前会发…

智能运维场景 | 科技风险预警,能实现到什么程度?

[ 原作者&#xff1a;擎创夏洛克&#xff0c;本文略做了节选和改编 ] 每次一说到“风险预警”&#xff0c;就会有客户问我们能做怎样的风险预警。实际上在智能运维厂商来说&#xff0c;此风险非彼风险&#xff0c;不是能做银行的业务上的风险预警&#xff08;比如贷款风险等&a…

自动化测试框架 Selenium(3)

目录 1.前言 2.等待方式 2.1死等 2.2智能等待 3.游览器操作 3.1游览器最大化 3.2设置游览器的宽 高 3.3 游览器的前进和后退 3.4游览器滚动条 1.前言 本篇博客,我们将继续Selenium自动化测试的学习.在前面的章节中,俺介绍了Selenium是怎么回事,和键盘鼠标操作.还有url和…

2024年第十七届 认证杯 网络挑战赛 (A题)| 保暖纤维的保暖能力 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看认证杯 网络挑战赛 (A题&#xff09;&#xff01…

ruoyi-nbcio-plus基于vue3的flowable的支持自定义业务流程处理页面detail.vue的升级修改

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

Qt | 信号与槽 原理、连接、断开(面试无忧)

1、信号和槽是用于对象之间的通信的,这是 Qt 的核心。为此 Qt 引入了一些关键字,他们是slots、signals、emit,这些都不是 C++关键字,是 Qt 特有的,这些关键字会被 Qt 的 moc转换为标准的 C++语句。 2、Qt 的部件类中有一些已经定义好了的信号和槽,通常的作法是子类化部件…

2023年上半年信息系统项目管理师——综合知识真题与答案解释(1)

2023年上半年信息系统项目管理师 ——综合知识真题与答案解释(1) 零、00时光宝盒 1009 Rejections 1009 拒绝 Once, there was an old man, who was broke, living in a tiny house and owned a beat-up car. 有一次&#xff0c;有一个老人&#xff0c;他破产了&#…

谷歌google浏览器无法更新Chrome至最新版本怎么办?浏览器Chrome无法更新至最新版本

打开谷歌google浏览器提示&#xff1a;无法更新Chrome&#xff0c;Chrome无法更新至最新版本&#xff0c;因此您未能获得最新的功能和安全修复程序。点击「重新安装Chrome」后无法访问此网站&#xff0c;造成谷歌浏览器每天提示却无法更新Chrome至最新版本。 谷歌google浏览器无…

Netty源码解析-服务启动过程

文章目录 前言简单Netty服务器启动代码示例主线NioEventLoopGroup初始化关键代码 前言 Netty是一个高性能、异步事件驱动的网络应用框架&#xff0c;用于快速开发可维护的高性能协议服务器和客户端。它的服务启动过程涉及多个组件和步骤&#xff0c;下面我将对Netty的服务启动…

OpenAI推出GPTBot网络爬虫:提升AI模型同时引发道德法律争议

文章目录 一、GPTBot 简介二、功能特点三、技术细节3.1、用户代理标识3.2、数据采集规则3.3、数据使用目的3.4、网站屏蔽方法3.5、数据过滤 四、GPTBot 的道德和法律问题五、GPTBot 的使用方法和限制六、总结 一、GPTBot 简介 OpenAI 推出的网络爬虫GPTBot旨在通过从互联网上收…

腾讯云向量数据库——RAG七天入门课笔记

目录 前言一、RAG介绍1-0、引言-大语言模型的不足1-1、向量数据库定义1-2、工作原理1-3、优点1-4、与传统数据库的区别1-5、RAG应用痛点 二、数据处理的难点——解析和拆分2-1、复杂文档格式-解析过程中的问题2-2、复杂文档解决流程2-3、Chunk拆分的问题以及如何改进 三、相似性…

【GitHub技术全面解析及游戏开发者的应用】

GitHub技术全面解析及游戏开发者的应用 GitHub作为全球最大的开源代码托管平台&#xff0c;不仅为软件开发者提供了一个强大的工具&#xff0c;也为游戏开发者带来了前所未有的便利。在游戏开发领域&#xff0c;GitHub的技术可以帮助开发者更高效地管理代码、协作开发、分享资…

10 - 镜像管理之:部署高可用harbor

之前介绍了部署单点harbor&#xff0c;这里重点说下Harbor高可用集群方案的部署&#xff0c;目前主要有两种主流的Harbor高可用集群方案&#xff1a; 1&#xff09;双主复制 2&#xff09;多harbor实例共享后端存储 1 Harbor双主复制高可用集群 1.1 主从同步 harbor官方默认提供…

arm64位系统中编译ffmpeg

大致过程仍然和x86平台一致&#xff1a; ./configure xxxxmakemake install 所需要变化的是需要在 ./configure xxxx 后面多加几个编译选项 cd ffmpeg ./configure (x64下的依赖配置&#xff1a;......)--prefixbin --archaarch64 --target-oslinux --enable-cross-compile …

redis的客户端操作

文章目录 前言Java客户端Jedis准备工作引入JedisJedis的基本使用方法String类型的操作List类型操作Hash类型操作Set类型操作Zet类型的操作 JavaSpring客户端创建项目引入SpringDataRedis配置 redis 服务地址创建 Controller具体实例 前言 Redis是用单线程来处理多个客户端的访…

【linux深入剖析】深入理解软硬链接 | 动静态库的制作以及使用

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1.理解软硬链接1.1 操作观…

Linux_网络编程套接字_2

文章目录 一、预备知识认识端口认识TCP协议认识UDP协议网络字节序 二、socket编程接口1.socket常见API2.socket结构总结 3.其他接口1.IP地址《》整数 inet_addr等等2.读取报文 - recvfrom 三、简单的UDP网络程序 - 聊天室1.源代码展示 四、TCP1.编写TCP服务器程序1.创建套接字 …

三行命令解决Ubuntu Linux联网问题

本博客中Ubuntu版本为23.10.1最新版本&#xff0c;后续发现了很多问题我无法解决&#xff0c;已经下载了另外一个版本22.04&#xff0c;此版本自带网络 一开始我找到官方文档描述可以通过命令行连接到 WiFi 网络&#xff1a;https://cn.linux-console.net/?p10334#google_vig…

网络协议——RSTP(快速生成树)与MSTP(多实例生成树)

一. RSTP 1. STP的不足 1、依靠计时器超时的方式进行收敛导致它的收敛时间需要30到50秒 2、端口状态和端口角色没有细致区分&#xff0c;指导数据转发依靠的不是端口状态而是端口所扮演角色。 3、如果拓扑频繁变化导致用户通信质量差&#xff0c;甚至通信中断&#xf…

【THM】What the Shell?(什么是壳?)-初级渗透测试

什么是shell? 在我们深入了解发送和接收 shell 的复杂性之前,了解 shell 的实际含义非常重要。用最简单的术语来说,shell 是我们与命令行环境 (CLI) 交互时使用的工具。换句话说,Linux中常见的 bash 或 sh 程序都是 shell 的例子,Windows 上的 cmd.exe 和 Powershell 也是…