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 同时存在,只会执行 onErrortestFuture().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 })
initialData | Future完成前的初始化数据 |
---|---|
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(),);}
}