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 })
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(),
);
}
}